6 Step 3: Crates and Entity Entity Collision
sadpmpk edited this page 2023-03-19 00:26:08 -04:00

Now that the player is ready and can move about with tiles, it's time to add a new entity to interact with: crates.

Crates are pretty much the building block of the original game. Most other items are contained with crates (or containers) for the player to interact with. I thought this would the best way to begin implementing entity-to-entity collision handling.

Collision System Part II

Previously, the collision system has to deal with tiles only, which are static in the tilemap system. Now, the collision system need to handle dynamic entities. Thankfully, I have already implemented a broad-phase collision detection to help culling out unnecessary collision check. The narrow phase collision should also work given that all entities are also AABB.

However, there are some things that were considered during the design:

  • Not all entities will push other entities away. Sometimes, it is okay for entities to overlap.
  • Other than handling overlap, entity-entity collision will need to interact with each other. This interaction varies between different pairs of entities.
  • When handling collision events, duplicate events should be skipped or prevented

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.

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.

Crates

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.

typedef enum ContainerItem
{
    CONTAINER_EMPTY,
    CONTAINER_LEFT_ARROW,
    CONTAINER_RIGHT_ARROW,
    CONTAINER_UP_ARROW,
    CONTAINER_DOWN_ARROW,
    CONTAINER_COIN,
    CONTAINER_BOMB,
}ContainerItem_t;

typedef enum ContainerMaterial
{
    WOODEN_CONTAINER,
    METAL_CONTAINER,
}ContainerMaterial_t;

typedef struct _CContainer_t
{
    ContainerMaterial_t material;
    ContainerItem_t item;
}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.

Crate Bashing

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.

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 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

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

typedef struct _CHitBoxes_t
{
    Rectangle boxes[2];
    uint8_t n_boxes;
    bool strong;
}CHitBoxes_t;

typedef struct _CHurtbox_t
{
    Vector2 offset;
    Vector2 size;
    bool fragile;
}CHurtbox_t;