1
\$\begingroup\$

I'm making a little top down 2D dungeon crawler, and have pretty much fallen over at collision detection with my dungeon walls. I have figured out how to stop my player sprite at the walls, but I'm having trouble with the seams of the vertical walls. Horizontal walls, for some reason, are giving me absolutely no issue.

I store a bunch of rectangles representing the dungeon walls, and for each entity that is of the type RigidBody.Type.Moving, I collision check using a projection of where the entity will be based on its current X & Y velocity (against all rectangles, at the moment).

My player gets stuck at spots where the vertical wall meets with horizontal lines.


Here is my collision detection code:

var dt = (float) gameTime.ElapsedGameTime.TotalSeconds;
var rb = entity.GetComponent<RigidBody>();
var body = rb.Body;

// We only want to do collision checks for bodies that are moving.
if (rb.Type != RigidBody.Type.Moving) return;

// Don't collision check against itself!
var rectangles = CollisionWorld.Instance.Bodies.Where(b => b != body);
foreach (var rectangle in rectangles)
{
    // Work out where the entity is going to be next with its current velocity
    // and store it as a rectangle to collision check on.
    var projectedBody = new Rectangle(
        (int)(rb.Position.X + rb.Velocity.X * dt), 
        (int)(rb.Position.Y + rb.Velocity.Y * dt), 
        body.Width, body.Height);

    // If we have a collision, continue. Otherwise move on.
    if (!Collision.DoesCollide(projectedBody, rectangle)) continue;
    var side = Collision.CalulateCollisionSide(projectedBody, rectangle);

    if (side == Collision.Side.Top || side == Collision.Side.Bottom)
    {
        rb.Velocity.Y = 0;
    }
    if (side == Collision.Side.Left || side == Collision.Side.Right)
    {
        rb.Velocity.X = 0;
    }
}

I have tried finding the collision intersection, and using it to offset the player's position. by that and that kinda works, but then the sprite is all jittery whenever it collides. I've been bashing my head against this for a couple of days, now.

Why would the seams between each vertical tile be causing my sprite to get stuck?

\$\endgroup\$
  • \$\begingroup\$ You probably have a rounding issue with the Velocity.X * dt & Velocity.Y * dt calculations. e.g. The calculation may cause a Top/Bottom collision but not a Left/Right collision. The next move would prevent the Top/Bottom collision but allow the Left/Right movement to continue. Thus, you are now overlapping the boundary. Since you are only using rectangles then any collision should set both the X & Y velocity to 0. Another option is to expand the projected rectangle size by the expected max possible movement and play some games with that. \$\endgroup\$ – Dunk May 18 '17 at 21:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.