Update 'Step 3: Crates and Entity Entity Collision'
parent
d3dc0005b5
commit
58141522e1
|
@ -11,29 +11,10 @@ However, there are some things that were considered during the design:
|
||||||
|
|
||||||
To address the first point, a new field is added to the bbox component - a 'solid' field to indicate that overlap in collision is allowed or not. Effectively, a non-solid bbox will not move other entities on collision.
|
To address the first point, a new field is added to the bbox component - a 'solid' field to indicate that overlap in collision is allowed or not. Effectively, a non-solid bbox will not move other entities on collision.
|
||||||
|
|
||||||
## Collision Event Resolution
|
The crate interaction involves one entity destroying another entity on interaction. This is not a unique interaction and will appear in future development. For this interaction, two new components are introduced: Hitbox and Hurtbox.
|
||||||
To address the second point, I've opt to collection all collision events during the collision detection phase. First, overlapping collisions are resolved alongside the detection. After that, all collision events are resolved one-by-one. This method keeps a clear line in the order of resolution, rather than mixing the different resolutions with the detection step.
|
|
||||||
|
|
||||||
To collect collision event, I need to encode the collision information for processing later. Currently, I've thought of these information that may be important:
|
|
||||||
- The pair of entities colliding
|
|
||||||
- The direction and magnitude of the overlap
|
|
||||||
I've decided to use a int-to-int map to store the collision event. There are alternatives to handling this, but somehow map makes the most sense to me at this point of time. Anyways, to make this work I would need to encode the information I want to keys and values for the map. This is want I settled on:
|
|
||||||
- The colliding pair is encoded as the key as a 32-bit integer. The most significant 16 bits is the current entity index and the least significant bits is the other entity index in the current. This method of encoding means that there is a theoretical entity limit of 65535. However, I do not see the need for such a high entity number for this small game.
|
|
||||||
- The collision overlap is encoded into a 16 bit integer value, associated to the colliding pair key. The most significant 2 bits encodes the direction of collision. This is fine as there is only 4 possible directions in AABB collisions: up, down, left, right. The remaining 14 bits are to encode the magnitude of overlap. This gives a maximum overlap value of 16383, which is more than enough.
|
|
||||||
### Alternative Storage
|
|
||||||
Of course, the above method can be implemented differently. After reviewing the data, it is possible to encode the entire information into a singular 64 bits integer. Then, either a vector or a queue data structure can be used to store the data. For readability, a struct with bit fields (or just regular fileds) can be used as well. In this case, the vector data structure should be used.
|
|
||||||
## Duplicate Collision
|
|
||||||
Thus far, there is not a way to detect if a pair of entity has been checked. In fact, this is deliberate. Entity A colliding with Entity B would be handled differently from when Entity B is colliding with Entity A.
|
|
||||||
|
|
||||||
That said, two measures has been implemented to reduce down collision check:
|
|
||||||
- Every entity has a tag. One way to prevent duplicate collisions is to only allow one-way collision based on the tag. As the tag is essentially an integer, we will only check for collision if the current entity tag is lower or equal to the other entity tag. This way, the tag is used as a priority in collision detection.
|
|
||||||
- A bool array is used to check if an entity has already been checked against. This array is refreshed for each loop through an entity.
|
|
||||||
These two methods does not completely remove duplicate collisions. However, it works good enough. This topic will be revised if needed.
|
|
||||||
|
|
||||||
# Crates
|
# Crates
|
||||||
|
|
||||||
Now that the entity-entity collision is ready, it's time to implement crates and its interaction.
|
|
||||||
|
|
||||||
## Components Creation
|
## Components Creation
|
||||||
Crates itself isn't the hardest to implement. By right, crates would have the expected components and the systems written thus far should able to handle its collision and movement. However, crates (and some other items later on) are meant to contain another entity to spawn. Thus, a new component is created to handle this behaviour down the line.
|
Crates itself isn't the hardest to implement. By right, crates would have the expected components and the systems written thus far should able to handle its collision and movement. However, crates (and some other items later on) are meant to contain another entity to spawn. Thus, a new component is created to handle this behaviour down the line.
|
||||||
```c
|
```c
|
||||||
|
@ -62,27 +43,36 @@ typedef struct _CContainer_t
|
||||||
```
|
```
|
||||||
In the original game, there are two types of crates: wooden and metal. Furthermore, a container can only contain a selection of items as seen above. This is a small peek on the entities that are going to be implemented later on.
|
In the original game, there are two types of crates: wooden and metal. Furthermore, a container can only contain a selection of items as seen above. This is a small peek on the entities that are going to be implemented later on.
|
||||||
## Crate Bashing
|
## Crate Bashing
|
||||||
The interaction is simple for now: when the player collides with a crate, it needs to destroy itself, while the player is given an upward velocity if its bottom is above the crate. The player should not overlap with the crate on collision, so the crate is 'solid'.
|
The interaction is simple for now: when the player collides with a crate, the player hitbox should collide with the crates hurtbox. On collision, the crates should destroy itself. If the player is above the crate, it should be given an upwards velocity, thus bouncing the player. A system is written to handle generically the interaction between hitbox and hurtbox. The crate-with-player specific logic is added to that system.
|
||||||
|
|
||||||
During the implementation, there was an interesting edge case: if the player has no downwards velocity, the crate is not destroyed when the player walk on top on the crates. This is possible if the player starts on a solid tile and moves forward onto a crate. This is because crates are destroy **ONLY IF THERE IS A COLLISION WITH IT**. This edge case does not create a collision since the player is technically on ground when walking over the crate, therefore no gravity is applied, hence no collision occurs.
|
As mentioned above, there is a second type of crate: metal crate. These crates can still be destroyed but not by merely colliding with it. To differentiate between the interaction between a regular crate and metal crate, a 'fragile' field is introduced in the HurtBox component, and a 'strong' field is introduced in the HitBox Component.
|
||||||
|
|
||||||
The first remedy for this edge case would be to check below the player for a crate and apply the interaction, instead of just checking for collision. However, I didn't quite like this solution as this is too specific of a solution to crates. It is possible that the same edge case can occur with new entities.
|
The interaction logic is as such:
|
||||||
|
- Any HitBox can destroy a _fragile_ HurtBox
|
||||||
|
- A non _strong_ HitBox cannot destroy a _non-fragile_ HurtBox
|
||||||
|
- A _strong_ HitBox can destroy a _non-fragile_ HurtBox
|
||||||
|
|
||||||
So, the second solution would be to somehow apply gravity when the player is on top of a crate, thus creating a collision for the interaction to occur. To apply gravity, I would need to somehow tell the player that it isn't on ground when on top of a crate. Mind you that there is two types of crates: wooden and metal. Therefore, this interaction should only be applied to wooden crates. To handle this, I've introduced a new field in bbox component: fragile.
|
This works well enough. To extend this, a power level system should be introduced instead of using boolean. A HurtBox can have a defense value, while a HitBox can have a attack value. A HitBox with a higher or equal attack value to the defense value a hurtbox can destroy that HurtBox.
|
||||||
|
|
||||||
|
|
||||||
|
_Credits to Baba Is You for the fragile and strong fields inspiration_
|
||||||
|
|
||||||
|
## Corner Collision Handling
|
||||||
|
To allow the player to collide with a crate, the Hitbox of the player is an AABB, extended out of the Bbox in each direction by one pixel. One of the bug of this implementation is that it allows player to destroy a crate across an enclosed corner. To solve this, the player is given two HitBoxes instead, assembled to be a cross shape. With this, the corner collision is avoided while retaining the AABB collision system. This introduces and extra AABB check, but should be acceptable at this point.
|
||||||
|
|
||||||
|
### HitBox and HurtBox
|
||||||
```c
|
```c
|
||||||
typedef struct _CBBox_t
|
typedef struct _CHitBoxes_t
|
||||||
|
{
|
||||||
|
Rectangle boxes[2];
|
||||||
|
uint8_t n_boxes;
|
||||||
|
bool strong;
|
||||||
|
}CHitBoxes_t;
|
||||||
|
|
||||||
|
typedef struct _CHurtbox_t
|
||||||
{
|
{
|
||||||
Vector2 size;
|
|
||||||
Vector2 offset;
|
Vector2 offset;
|
||||||
Vector2 half_size;
|
Vector2 size;
|
||||||
bool solid;
|
|
||||||
bool fragile;
|
bool fragile;
|
||||||
}CBBox_t;
|
}CHurtbox_t;
|
||||||
```
|
```
|
||||||
The _solid_ field determines if an entity pushes other entity way to prevent overlapping, and the _fragile_ field determines if the entity should destroy itself on collision. With the new field, an entity is considered on ground if it is on a solid tile, or it is on an entity that is solid AND not fragile.
|
|
||||||
|
|
||||||
With the new field, the interaction can differ between wooden crates and metal crates:
|
|
||||||
- Wooden crates: solid and fragile
|
|
||||||
- Metal crates: solid and not fragile
|
|
||||||
|
|
||||||
_Credits to Baba Is You for the inspiration_
|
|
Loading…
Reference in New Issue