I have implemented a simple rectangle based collsion detection where you can "slide" around the edges on diagonal movement. Works fine but the thing is, it is somehow possible that e.g. the player (rectangle) glitches into the one of a collision object. It seems, that it appears only when the player "slides" around the corners. I suspect that if the player walks around the corners that the movement direction (Vector2) cuts off the corner and at some point glitches into the collision rectangle.
I hope I've explained the problem somehow understandable?
The code looks like this:
The UpdateCall recieves the playerMovement from the keyboard input
public void UpdatePlayer(GameTime gameTime, Vector2 playerMovement)
{
//...
playerMovement = CalculatePlayerMovement(Vector2.Normalize(playerMovement) * movementspeed);
if (playerMovement.Length() != 0)
MoveBy(playerMovement);
//...
}
The CalculatePlayerMovement-Method checks world bounds, collision objects and so on. Depending on what side the collsion happens, the x- or y-movement will be zeroed.
private Vector2 CalculatePlayerMovement(Vector2 movement)
{
Rectangle destRect = new Rectangle(BoundingBox.X + (int)movement.X, BoundingBox.Y + (int)movement.Y, Width, Height);
Vector2 returnValue = movement;
//...
foreach (Rectangle r in TileMap.collisionObjects)
{
if (destRect.Intersects(r))
{
string collsionSide = GetCollisionSide(destRect, r);
if (collsionSide == "top" || collsionSide == "bottom")
returnValue.Y = 0;
if (collsionSide == "left" || collsionSide == "right")
returnValue.X = 0;
}
}
//...
}
Finally the check itself. I took this part from HERE since I was not sure what the best way would be.
private string GetCollisionSide(Rectangle destRect, Rectangle r)
{
float w = (destRect.Width + r.Width) / 2;
float h = (destRect.Height + r.Height) / 2;
float dx = destRect.Center.X - r.Center.X;
float dy = destRect.Center.Y - r.Center.Y;
if (Math.Abs(dx) <= w && Math.Abs(dy) <= h)
{
float wy = w * dy;
float hx = h * dx;
if (wy > hx)
{
if (wy > -hx)
return "top";
else
return "right";
}
else if (wy < hx)
{
if (wy > -hx)
return "left";
else
return "bottom";
}
}
return "";
}
I am not sure where the problem is, but it is probably something I don't see myself.