23
\$\begingroup\$

I'm writing a top down 2d XNA game. Since its my first I'm trying to write the physics and collision stuff myself to learn it.

Whenever my player sprite character attempts to move into a position where its bounds intersect with the edge of a wall, I figure out a bounce angle (angle of incidence = angle of reflection) and I make the player bounce off the wall and avoid the collision.

I'm having trouble figuring out how to deal with the situation of my sprite intersecting with two wall edges simultaneously though e.g. it hits a corner.

corner collision

My code currently tells me that two wall edges have been intersected but not which edge it would have hit first and therefore which edge to bounce off.

What is the mathematical test to pick which edge to bounce off? It's plain to see when looking at it but I'm struggling to figure out the math test for it.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ gamedev.stackexchange.com/questions/10911/… \$\endgroup\$
    – Tetrad
    Commented Sep 21, 2011 at 1:29
  • \$\begingroup\$ Thanks Tetrad. I saw that one but it looked like the ball would behave differently to my rectangular problem. In the case illustrated above the rectangular sprite would have hit the bottom edge of the wall and bounced off it. The side edge of the wall would never have come into the equation. I just don't know how to express that in code and make that decision. \$\endgroup\$
    – TerryB
    Commented Sep 21, 2011 at 2:04

4 Answers 4

10
\$\begingroup\$

If you calculate how far into the Wall the Player Sprite has moved, you can probably base it on the delta of the x and y coordinates of the corners that are intersecting. I hope that makes sense, I can't think of a better way to word it.

So, for example, if you look at your diagram. Take the x value of the top left corner of the Player Sprite (after the move), and subtract the x value of the bottom right corner of the Wall. Do the same thing for the y values and then see which one is larger. The key is that if one is larger than the other, the Player Sprite probably intersected on that side.

Here's an image example (this is a subsection of your image with my own lines added):

intersection example

Now, you see here that the blue line is larger than the green line. In this case the blue line is also on the side that the Player Sprite would be expected to bounce off of.

If the two values are equal, they hit right on the corner.

Now, there is a slight problem with doing it this way. If the Player Sprite is traveling very fast or the collision is very close to the corner, it's possible that the Player Sprite may go further into the Wall in the wrong direction. In that case you'll probably have to check the velocity of the moving object. (See Nathan Reed's answer.)

Note: I think I'm essentially trying to describe the SAT collision detection that @Blau mentioned, but I've spent a long time writing this so I'm going to post it anyways. Hopefully it'll help you some.

\$\endgroup\$
6
  • \$\begingroup\$ Thanks Drackir! And I guess if my wall is rotated relative to the sprite its a bit trickier but same principle applies. Look for the minimum length displacement vector that would mean the sprite would not collide with the wall. Then use the wall that is normal to that vector as my one to bounce off. \$\endgroup\$
    – TerryB
    Commented Sep 21, 2011 at 3:26
  • \$\begingroup\$ @TerryB - Rotation adds a bit more complexity to it. You may want to read up on axis-aligned bounding boxes (AABB). Basically, you still use the same principle as above by testing the smallest box that the rotated object will fit into, but whose axes are aligned to the cartesian axes. Imagine if you had a square and you rotated it 45 degrees to make it a diamond. Calculating the collision on that would be difficult and costly, so first check to see if the object is even near it by using the AABB which would be a square where each point of the diamond touches each side in the middle. \$\endgroup\$ Commented Sep 21, 2011 at 4:06
  • \$\begingroup\$ Then, when you know it's near it, you can do the more costly calculations to see if they intersect on angles (which should probably be another question altogether :) ). \$\endgroup\$ Commented Sep 21, 2011 at 4:10
  • 1
    \$\begingroup\$ -1 since minimum displacement does not always give the correct answer to "which edge collided first"; see my answer. \$\endgroup\$ Commented Jan 19, 2012 at 17:53
  • \$\begingroup\$ @NathanReed - Which is why I mentioned checking the velocity in my "Now, there is a slight problem with doing it this way" paragraph. \$\endgroup\$ Commented Jan 19, 2012 at 19:42
17
\$\begingroup\$

Minimum displacement does not always give the right answer for which edge was hit first. Consider this case:

case that breaks shortest-displacement algorithm

This happens when the velocity is high enough that the block moves rather far during one frame. To correctly detect which edge was hit first, you'll need to set up a linear equation to solve for the time of collision with each edge. In this case described in the OP's diagram, the relevant equations are:

timeXCollision = (player.left - wall.right) / -player.velocity.x
timeYCollision = (wall.bottom - player.top) / player.velocity.y

(This is assuming an X-right, Y-up coordinate system.) In general, you'd have to use the signs of player.velocity's X and Y components to determine which pair of edges need to be tested. Anyway, once you have the collision times computed, the earlier of the two is the collision you need to handle.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Could you provide an example on how your two variables could be implemented? \$\endgroup\$
    – BjarkeCK
    Commented May 21, 2014 at 21:56
2
\$\begingroup\$

You need SAT Collision Detection

Basically you need to look for the minimum displacement vector that substracted to one of the objects let them to no intersect.

In your image the minimum displacement is the orange segment.

enter image description here

\$\endgroup\$
10
  • 4
    \$\begingroup\$ -1 since minimum displacement does not always give the correct answer to "which edge collided first"; see my answer. \$\endgroup\$ Commented Jan 19, 2012 at 17:52
  • \$\begingroup\$ who are asking that? \$\endgroup\$
    – Blau
    Commented Jan 19, 2012 at 23:13
  • \$\begingroup\$ The question is asking that. "My code currently tells me that two wall edges have been intersected but not which edge it would have hit first and therefore which edge to bounce off." \$\endgroup\$ Commented Jan 20, 2012 at 0:02
  • \$\begingroup\$ first? the problem is not what is the first, it collides with the two edges at the same time,... the matter is which edge to bounce off, you have choose one method that is good to you, I have choosed a method that is good to me, both are valid \$\endgroup\$
    – Blau
    Commented Jan 20, 2012 at 12:25
  • 1
    \$\begingroup\$ If you want to make a design decision to let objects slip past each other like that, as if they were rounded or beveled on the corners, that's your decision, and may well be the right thing for your gameplay. But I don't think the question is asking about a design decision; it is asking mathematically how to bounce axis-aligned rectangles off each other. This is not a matter of interpretation; this math problem has a clear and correct answer to which edge to bounce off. \$\endgroup\$ Commented Jan 21, 2012 at 19:29
0
\$\begingroup\$

Answered a similar question here

You may want to consider checking previous positions-

For example : if your left side was previously to the right of their right side and you're colliding, then a right hand collision has happened.

If you do this, just resolve y axis collisions, check if you're colliding with anything, then resolve x axis collisions.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .