“You play as a warlock´s apprentice on your way back from buying baguettes. When you return to the castle, you find it overrun with your masters failed experiments. Save your master by clearing out the courtyard.”
About Warlock Activities
Warlock Activities was the fourth game project at TGA and our last project in our first year. We were tasked with creating an adventure game. We based our game on Death’s Door and used it as a reference game. We decided to make the game using an ECS (Entity Component System) architecture. Using an external library called entt as a base.
Kim Betsgren Marcus Carlson Oscar Hofling Sebastian Brymell
Animators:
Guzalya A Tynnhammar Tim Lee
Level Designers
Ahab Ibrahim Erik Gatewood
Music & SFX Artists
Ludvig Dejinoff Oscar Bjurström
My Contribution
Collision System
TGE does not have a collision system built in like off the shelf engines such as Unity or Unreal. I took it upon me to create our collision system. The systems only goal was make sure that object wouldn’t clip into each other. The biggest challenge that I faced was integrating collisions into the ECS framework.
At first I planned to use the visitor pattern because I had recently learned of it. But as I was working on it I realised that it was going against one of the core principles of ECS. Components have no behaviour and systems have no state. I ended up scrapping the system I had built up to follow this principle.
The collider component is base struct that is inherited by the two types of colliders, Sphere and Box colliders. Each collider contains data about itself. Most interesting are myMoveability, myCollisionLayer and myCollisionMask. Note:Looking back at the code I can’t remember why the box collider contains an array of three floats instead of a fVector3 and I don’t know if there is a good explanation. Also the reason the sizes are not in the transform is because I wanted to make the logic easier to understand for myself.
Collision Layers and Masks The collision layer and mask are there so we can decide if a certain colliders should interact with each other. Let’s say we have a button that only the player should be able to activate and enemies should be ignored. We can but the enemy collider on an “Enemy Layer” and the player collider on a specific “Player Layer” and the buttons collision mask will have a value called “Player Mask”. Now when an enemy steps on the button, the buttons collision mask does not match with the enemy collision layer and won’t activate. But when the player steps on the button, the players layer and the buttons mask match and the button will register that it was pressed. Critically in this example the player would not know that the button has been pressed. For that to happen the button would have to have a layer that matches the players mask. It can be thought of that the layer is something a collider is e.g. “Player Layer” “Enemy Layer” “Button Layer”, and masks say what layers a colliders is ‘looking at’. A button is looking at the “Player Layer” to see when it collides.
Collider Moveability All the collision logic is done using ‘static’ calculations. Which means the system only knows the colliders current location and not the previous location. This made it difficult when a collision had occurred and the colliders had to be moved as I had no idea which object moved into the other, or if both objects moved into each other. When I first built the system I noticed that when I moved the player into a wall the wall would move as well. This was because during the collision calculations I find the shortest vector that would make the two objects no longer collide and move both object half that vector in opposite directions.
enumclassColliderMovability : uint8_t
{
Immovable = 0,
Movable = 1,
LightWeight = 2,
};
To fix this issue each collider gets a moveability value. There are three “Immovable”, “Movable” and “LightWeight”. With these three I could decide what should happen when the system needs to move two colliders. If they have the same moveability value it works as before. But if the two object have different moveabilities the one with a higher value will move the entire seperation vector.
Some caveats with the system are that I could not figure out how to correctly calculate the separation vector when two box colliders collided. which causes some weird bugs.
At the end of the day we decided that the player and the enemies, the only things in the game that moved and needed to have correct separation vectors simply got sphere colliders. Once the final implementation was finished I could do stuff like this. Where the walls are “Immovable” the player is “Moveable” and the balls are “LightWeight”
Warlock Activities
“You play as a warlock´s apprentice on your way back from buying baguettes. When you return to the castle, you find it overrun with your masters failed experiments. Save your master by clearing out the courtyard.”
About Warlock Activities
Warlock Activities was the fourth game project at TGA and our last project in our first year. We were tasked with creating an adventure game. We based our game on Death’s Door and used it as a reference game. We decided to make the game using an ECS (Entity Component System) architecture. Using an external library called entt as a base.
Kim Betsgren Marcus Carlson Oscar Hofling Sebastian Brymell
Animators:
Guzalya A Tynnhammar Tim Lee
Level Designers
Ahab Ibrahim Erik Gatewood
Music & SFX Artists
Ludvig Dejinoff Oscar Bjurström
My Contribution
Collision System
TGE does not have a collision system built in like off the shelf engines such as Unity or Unreal. I took it upon me to create our collision system. The systems only goal was make sure that object wouldn’t clip into each other. The biggest challenge that I faced was integrating collisions into the ECS framework.
At first I planned to use the visitor pattern because I had recently learned of it. But as I was working on it I realised that it was going against one of the core principles of ECS. Components have no behaviour and systems have no state. I ended up scrapping the system I had built up to follow this principle.
The collider component is base struct that is inherited by the two types of colliders, Sphere and Box colliders. Each collider contains data about itself. Most interesting are myMoveability, myCollisionLayer and myCollisionMask. Note:Looking back at the code I can’t remember why the box collider contains an array of three floats instead of a fVector3 and I don’t know if there is a good explanation. Also the reason the sizes are not in the transform is because I wanted to make the logic easier to understand for myself.
Collision Layers and Masks The collision layer and mask are there so we can decide if a certain colliders should interact with each other. Let’s say we have a button that only the player should be able to activate and enemies should be ignored. We can put the enemy collider on an “Enemy Layer” and the player collider on a specific “Player Layer” and the buttons collision mask will have a value called “Player Mask”. Now when an enemy steps on the button, the buttons collision mask does not match with the enemy collision layer and won’t activate. But when the player steps on the button, the players layer and the buttons mask match and the button will register that it was pressed. Critically in this example the player would not know that the button has been pressed. For that to happen the button would have to have a layer that matches the players mask. It can be thought of that the layer is something a collider is e.g. “Player Layer” “Enemy Layer” “Button Layer”, and masks say what layers a colliders is ‘looking at’. A button is looking at the “Player Layer” to see when it collides.
Collider Moveability All the collision logic is done using ‘static’ calculations. Which means the system only knows the colliders current location and not the previous location. This made it difficult when a collision had occurred and the colliders had to be moved as I had no idea which object moved into the other, or if both objects moved into each other. When I first built the system I noticed that when I moved the player into a wall the wall would move as well. This was because during the collision calculations I find the shortest vector that would make the two objects no longer collide and move both object half that vector in opposite directions.
enumclassColliderMovability : uint8_t
{
Immovable = 0,
Movable = 1,
LightWeight = 2,
};
To fix this issue each collider gets a moveability value. There are three “Immovable”, “Movable” and “LightWeight”. With these three I could decide what should happen when the system needs to move two colliders. If they have the same moveability value it works as before. But if the two object have different moveabilities the one with a higher value will move the entire seperation vector.
Some caveats with the system are that I could not figure out how to correctly calculate the separation vector when two box colliders collided. which causes some weird bugs.
At the end of the day we decided that the player and the enemies, the only things in the game that moved and needed to have correct separation vectors simply got sphere colliders. Once the final implementation was finished I could do stuff like this. Where the walls are “Immovable” the player is “Moveable” and the balls are “LightWeight”