# Resolving 2D Collision with Rectangles

For about a week I've been trying to grasp the basics of collision, but I've been driven to the point of wanting to just give up on everything when it comes to collision. I just don't understand it. Here's my code so far:

`````` public static void ObjectToObjectResponseTopDown(GameObject actor1, GameObject actor2)
{
if (CollisionDetection2D.BoundingRectangle(actor1.Bounds.X, actor1.Bounds.Y, actor1.Bounds.Width, actor1.Bounds.Height,
actor2.Bounds.X, actor2.Bounds.Y, actor2.Bounds.Width, actor2.Bounds.Height)) //Just a Bounding Rectangle Collision Checker
{
if (actor1.Bounds.Top > actor2.Bounds.Bottom) //Hit From Top
{
actor1.y_position += Rectangle.Intersect(actor1.Bounds, actor2.Bounds).Height;
return;
}
if (actor1.Bounds.Bottom > actor2.Bounds.Top) //Hit From Bottom
{
actor1.y_position -= Rectangle.Intersect(actor1.Bounds, actor2.Bounds).Height;
return;
}
if (actor1.Bounds.Left > actor2.Bounds.Right)
{
actor1.x_position += Rectangle.Intersect(actor1.Bounds, actor2.Bounds).Width;
return;
}
if (actor1.Bounds.Right > actor2.Bounds.Left)
{
actor1.x_position -= Rectangle.Intersect(actor1.Bounds, actor2.Bounds).Width;
return;

}
}
}
``````

Essentially what it does so far is correctly collides when the bottom of the first rectangle collides with the top of the second rectangle, but with the left an right sides it corrects it either above or below the tile, and when the top of the first rectangle collides with the bottom of the second rectangle, it slides right through the second rectangle.

I'm really not sure what to do at this point.

-
What is your desired outcome? Are you having trouble with the collision detection or the collision response? – Savlon Apr 7 '13 at 21:40
@Salvon My desired outcome is for the rectangles not to overlap, but not be redirected somewhere else. I'm having trouble with the response. – jatmdm Apr 7 '13 at 22:30

Your collision detection code looks like it's working fine, however your collision response appears to be causing the issue. This is evident if you step through how you are actually resolving two colliding bodies.

Let's take a look at the following example (assume the blue rectangle is actor1 and moving left):

As your code checks the top and bottoms bounds first, these are the first to be resolved and actor1's y position is adjusted like so:

The two bodies are now no longer colliding, but the collision wasn't resolved in the best way. This will almost always happen (unless the two rectangles' top and bottom bounds are perfectly in line) and the last two if statements will never be checked.

A primitive way to handle collision response would be to offset the rectangles by the smallest overlap; this would solve the problem in the above example, but you would still find some problems. A better approach would take an object's velocity into consideration, such as the answer found here.

-
I suppose this is the best answer, but it still doesn't explain the implementation of such a system, and the attached link doesn't explain it well enough for beginners. Thank you though. – jatmdm Apr 8 '13 at 0:28
The way I deal with this type of rectangle collisions is to check the position + velocity and if the predicted new position isn't overlapping another object then move to that position... Kind of similar to how you look somewhere before you walk there... If you are struggling trying to implement this type of collision response then write back here and after work I will post an example for you. Good luck – Savlon Apr 8 '13 at 0:40

As Alex indicated, your collision response is a very sharp "snap to edge" type of reaction, where if the two rectangles collide, one of them will instantaneously adjust its position to place it adjacent to the other.

That's not ideal behavior, but it isn't necessarily a problem either. The problem is that you return from each of your sequential if(collision) checks, which is why you only get a top/bottom edge alignment.

The early exit (which are correct for AABB collision detection) is not necessary in your collision response. Try something more like:

``````            if (actor1.Bounds.Top > actor2.Bounds.Bottom) //Hit From Top
{
actor1.y_position += Rectangle.Intersect(actor1.Bounds, actor2.Bounds).Height;
}
else if (actor1.Bounds.Bottom > actor2.Bounds.Top) //Hit From Bottom
{
actor1.y_position -= Rectangle.Intersect(actor1.Bounds, actor2.Bounds).Height;
}

if (actor1.Bounds.Left > actor2.Bounds.Right)
{
actor1.x_position += Rectangle.Intersect(actor1.Bounds, actor2.Bounds).Width;
}
elseif (actor1.Bounds.Right > actor2.Bounds.Left)
{
actor1.x_position -= Rectangle.Intersect(actor1.Bounds, actor2.Bounds).Width;
}
``````
-
I tried that, but collision from the top doesn't work with this, and it still snaps to edge. – jatmdm Apr 8 '13 at 1:28
It would still snap to edge, but I expected this to allow for snapping to edge regardless of the direction from which they approach each other. I don't have XNA installed on this machine, but it looks as if the y_position adjustment is backwards. Try reversing the += and -= in the if and elseif blocks of the top/bottom section. – LLL79 Apr 8 '13 at 1:51