2
votes

I have two rectangles, one player, one map. The player needs to not be able to walk through the map. Both the player and map have a rectangle with position and texture width and height, both also have a Vector position. Rectangle.Intersect() only outputs a boolean value, I cannot figure out how I might find out which side was collided with. I found this function here which outputs a Vector representing how much the rectangles overlapped.

public static Vector2 GetIntersectionDepth(this Rectangle rectA,                 Rectangle rectB)
    {
        // Calculate half sizes.
        float halfWidthA = rectA.Width / 2.0f;
        float halfHeightA = rectA.Height / 2.0f;
        float halfWidthB = rectB.Width / 2.0f;
        float halfHeightB = rectB.Height / 2.0f;

        // Calculate centers.
        Vector2 centerA = new Vector2(rectA.Left + halfWidthA, rectA.Top + halfHeightA);
        Vector2 centerB = new Vector2(rectB.Left + halfWidthB, rectB.Top + halfHeightB);

        // Calculate current and minimum-non-intersecting distances between centers.
        float distanceX = centerA.X - centerB.X;
        float distanceY = centerA.Y - centerB.Y;
        float minDistanceX = halfWidthA + halfWidthB;
        float minDistanceY = halfHeightA + halfHeightB;

        // If we are not intersecting at all, return (0, 0).
        if (Math.Abs(distanceX) >= minDistanceX || Math.Abs(distanceY) >= minDistanceY)
            return Vector2.Zero;

        // Calculate and return intersection depths.
        float depthX = distanceX > 0 ? minDistanceX - distanceX : -minDistanceX - distanceX;
        float depthY = distanceY > 0 ? minDistanceY - distanceY : -minDistanceY - distanceY;
        return new Vector2(depthX, depthY);
    }

This function will give negative numbers based on side, however I cannot figure out how to use them effectively. I tried:

Vector2 overlap =   RectangleExtensions.GetIntersectionDepth(map.Dungeon[x,y].BoundingBox, player.BoundingBox);
if (overlap.X > 0) //This should be collision on the left
{
    //Move the player back
}

However this causes some strange bugs, especially when attempting the same for the Y player and map values.

The question: How can collision detection be done in monogame with rectangles that would let you know which side was collided with, using this function or otherwise.

Thanks for any help!

1

1 Answers

1
votes

The Rectangle class in XNA has 4 properties that can be of use here:

Left, Top, Right and Bottom.

You can use these to determine which side(s) the collision took place from.

For example, consider the Player.Rectangle.Left > Map.Rectangle.Left. If this is true, then the collision could have ocurred on the right side (given that the left side of the player is bigger on the X axis than the map's, that means that the player is to the right of the left most point of the map).

Basically you can compare the X and Y coordinates of both rectangles. Apart from strange cases (like one rectangle being submerged entirely in another, or one rectangle being a super-set of the other) these should be sufficient to tell you the side they collisioned on.

A better way to check this would be by having the middle-point of the two shapes, that might also be an easier way to tell the relative positioning of the two objects.

Now, even though it is in 3D, you may find this post helpful.