spaL
spaL

Reputation: 686

How can I fix my collisions for a platformer type game?

I'm using OpenGL, EnTT, and C++ to try and recreate Super Mario World. Currently, when I move the player in one direction and it collides with a solid block, the collision detection and resolution works well. However, when the player tries to jump whilst constantly moving towards a wall, the top collision gets triggered, causing the player to stop and fall back down. I've searched the internet for a while now but I just couldn't resolve this issue. I'd appreciate any suggestions or advice.

Collision Code:

void GameUI::collision(const entt::entity &entity, const entt::entity &object) {
    const auto &ent {registry.get<Hitbox>(entity)};
    auto &phys {registry.get<Physics>(entity)};
    const auto &obj {registry.get<Hitbox>(object)};

    if (ent.btm >= obj.top || ent.top <= obj.btm
        || ent.left >= obj.right || ent.right <= obj.left)
        return;

    if (ent.btm < obj.top && ent.btm - phys.yVel >= obj.top) { // Bottom Collision
        moveY(entity, obj.top - ent.btm);
        phys.yVel = 0;
    } else if (ent.top > obj.btm && ent.top - phys.yVel <= obj.btm) { // Top Collision
        moveY(entity, obj.btm - ent.top);
        phys.yVel = 0;
    } else if (ent.left < obj.right && ent.left - phys.xVel >= obj.right) { // Left Collision
        moveX(entity, obj.right - ent.left);
        phys.xVel = 0;
    } else if (ent.right > obj.left && ent.right - phys.xVel <= obj.left) { // Right Collision
        moveX(entity, obj.left - ent.right);
        phys.xVel = 0;
    }
}

Upvotes: 0

Views: 207

Answers (1)

IWonderWhatThisAPIDoes
IWonderWhatThisAPIDoes

Reputation: 1048

You don't do any bound checking to see if you're actually crashing into the wall in any given direction. When the function detects that you are clipping (and does not return right off the top), this is what happens.

      The actual wall -->  ######### ------------ <-- The plane where the wall lies
                                   # o_
                                   # /\    <-- You, hitting your head on the top plane
                                   #  |\
                                   #
                                   # | | |

Because the top collision is checked before the side ones.

if (ent.top > obj.btm && ent.top - phys.yVel <= obj.btm)

Even though you may not be clipping through the bottom of the wall, you are:

  • Inside the wall (function does not return right away)
  • Below its top side
  • And have an upward velocity

... Which includes all the conditions for a detection of a top-side collision.

Upvotes: 0

Related Questions