Collision detection in platformer, how to fix my character sliding off the edges of platforms?

46 Views Asked by At

The character/player in my game will slowly slide off platforms once he is near the edge. How would I fix this? Ideally my character would remain on top of a platform even in a situation like this:enter image description here

My Player class (onCollision method being the relevant part):

class Player extends SpriteAnimationGroupComponent with HasGameRef<Gain>, KeyboardHandler, CollisionCallbacks {
  String character;
  Player({pos, this.character = "Ninja Frog"}) : super(position: pos);

  final double stepTime = 0.05;

  ...
  @override
  void onCollision(Set<Vector2> intersectionPoints, PositionComponent other) {
    if (other is Platform) {
      if (intersectionPoints.length == 2) {
        Vector2 mid = (intersectionPoints.elementAt(0) + intersectionPoints.elementAt(1)) / 2;
        Vector2 collisionNormal = absoluteCenter - mid;
        final seperationDist = (size.x / 2) - collisionNormal.length;
        collisionNormal.normalize();
        if (Vector2(0, -1).dot(collisionNormal) > 0.9) {
          _isOnGround = true;
        }
        position += collisionNormal.scaled(seperationDist);
      }
    }
    super.onCollision(intersectionPoints, other);
  }
}

My Platform class that represents walls, ground, ceiling of game:

class Platform extends PositionComponent with CollisionCallbacks {
  bool canJumpThrough;
  Platform({required Vector2 position, required Vector2 size, this.canJumpThrough = false}) : super(position: position, size: size);

  @override
  FutureOr<void> onLoad() {
    add(RectangleHitbox(collisionType: CollisionType.passive));
    return super.onLoad();
  }
}
2

There are 2 best solutions below

0
On

There are multiple ways to solve this, one way is to change to onCollisionStart instead of onCollision. Since onCollisionStart is only called once the collision begins you should keep the player and the platform overlapping with one pixel, and then once the player has moved off the platform onCollisionEnd will be called, and you can reactivate things like gravity.

The onCollision method you are using now will be called in each tick and there are probably some rounding errors that make the player slide.

1
On

I was experiencing the same problem in my game. For me it was the fact that I was using a circle hitbox for my player. Changing it to a rectangle hitbox worked but now it's not working well with the collision code.