Sign in to follow this  
Destroyer of Worlds

Separating 2 Rectangles

Recommended Posts

Is anyone able to explain how you separate two bounding rectangles without going into some super complex axis thereom that just goes way over my head? Here's what I have now, and it works if you're heading straight (not diagonal, just straight in any direction):
// I already moved the objects by their velocities * deltaTime.
foreach (CollisionRectangle body in _bodies)
{
	foreach (CollisionRectangle other in _bodies)
	{
		// We don't collide with eachother.
		if (body == other)
			continue;

		if (body.Intersects(other))
		{
			// Draw them as red.
			if (body is RectangularCollisionRectangle)
				g.DrawRectangle(new Pen(Color.Red), new System.Drawing.Rectangle((int)body.Position.X, (int)body.Position.Y, (int)body.Width, (int)body.Height));

			Vector2 bodyPosition = body.Position;
			Vector2 bodyVelocity = body.Velocity;
			Vector2 otherPosition = other.Position;
			Vector2 otherVelocity = other.Velocity;

			if (body.Velocity.X < 0)
			{
				bodyPosition.X = other.Position.X + other.Width;
				bodyVelocity.X = 0;
			}
			else if (body.Velocity.X > 0)
			{
				bodyPosition.X = other.Position.X - body.Width;
				bodyVelocity.X = 0;
			}

			if (body.Velocity.Y < 0)
			{
				bodyPosition.Y = other.Position.Y + other.Height;
				bodyVelocity.Y = 0;
			}
			else if (body.Velocity.Y > 0)
			{
				bodyPosition.Y = other.Position.Y - body.Height;
				bodyVelocity.Y = 0;
			}

			body.Position = bodyPosition;
			body.Velocity = body.Velocity;
		}
	}
}

It doesn't work for diagonals, and I understand why, it's just testing for an overlap but not an overlap with any sort of directional meaning. It works for going straight though. It'll move you away from the edge depending on what way you're going. I can fix it by moving by X, testing for overlap, moving X, then moving by Y, testing for overlap, moving Y but that doesn't seem very efficient. So is there some "easy" separating axis theoreom just for rectangles? cuz for this overhead shooter, thats all I care about. Thank you very much.

Share this post


Link to post
Share on other sites
Well, for one thing, your line body.Velocity = body.Velocity; looks wrong - you probably want body.Velocity = bodyVelocity;.

Aside from that... I'm not really sure what the problem is. I'm guessing this is meant to stop an object when it runs into something else - is that correct?

Share this post


Link to post
Share on other sites
You're right about that one line. I fixed that up.

You're right. I moved the objects, then I test for overlaps with body.Intersect(). That works just fine.

Now I'm trying to adjust it so that they're no longer touching, I don't want my player to be standing in the floor, I want him right on top. The problem is, when you're moving down and to the right, it basically goes like this:

"He's moving to the right, put him to the left of the box he's hitting. Okay he's moving down, put him above the box."

So you end up on the top left corner of the box instead of just ontop of the box and continuing to move to the right.

You get what I'm trying to say? I want him to be pushed away from the object just the right distance, depending on how he's moving. If he's falling and hits something, push him up. If he's running to the right, push him left.

Share this post


Link to post
Share on other sites
OK, I understand what's going on now.

You've already got the right idea in your first post - move along one axis first, respond to any collisions, then do the other axis. It's a fairly standard way to handle things and always worked fine for me back in the day [smile]

I wouldn't worry about the efficiency of that method too much; if performance becomes a problem, just look for some tricks you can do to minimize the number of collision checks. For example, don't bother trying to see if the player is running into something that isn't even on the screen, and so on.

Share this post


Link to post
Share on other sites
Won't that create big problems?

Take for example this:


|
|
[] |
___



Assuming that rectangle is moving southeast, if I move him by X first, it might say that he hit the wall and end up exploding (if it's a rocket or something).

Share this post


Link to post
Share on other sites
That's true, that particular case would be a problem. What you should be able to do is move the object, check for collision, and then move the object the shortest distance possible until it isn't colliding anymore. E.g. if you have to move 10 units on the X axis to stop colliding, or 4 units on the Y axis, then just move along Y and you're done. (Obviously, if the object is only moving in X and not moving at all along Y, then you use the X axis - the shortest-axis decision is only relevant for diagonally moving objects.)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this