Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

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.

share|improve this question
2  
    
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. –  TerryB Sep 21 '11 at 2:04
add comment

4 Answers

up vote 8 down vote accepted

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.

share|improve this answer
    
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. –  TerryB Sep 21 '11 at 3:26
    
@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. –  Richard Marskell - Drackir Sep 21 '11 at 4:06
    
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 :) ). –  Richard Marskell - Drackir Sep 21 '11 at 4:10
1  
-1 since minimum displacement does not always give the correct answer to "which edge collided first"; see my answer. –  Nathan Reed Jan 19 '12 at 17:53
    
@NathanReed - Which is why I mentioned checking the velocity in my "Now, there is a slight problem with doing it this way" paragraph. –  Richard Marskell - Drackir Jan 19 '12 at 19:42
show 1 more comment

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.

share|improve this answer
add comment

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.

share|improve this answer
add comment

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

share|improve this answer
1  
-1 since minimum displacement does not always give the correct answer to "which edge collided first"; see my answer. –  Nathan Reed Jan 19 '12 at 17:52
    
who are asking that? –  Blau Jan 19 '12 at 23:13
    
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." –  Nathan Reed Jan 20 '12 at 0:02
    
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 –  Blau Jan 20 '12 at 12:25
1  
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. –  Nathan Reed Jan 21 '12 at 19:29
show 3 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.