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.

Using XNA's built in Intersects() on two Rectangles, I can detect a collision and set my velocity to zero. However, the object is stuck there and can't get out! How can I resolve this collision properly?

share|improve this question

2 Answers 2

up vote 11 down vote accepted

This is because once your object gets into the wall and you find the collision, you're simply stopping the object's movement by setting its velocity to zero, but the object is still within that wall.

To fix it, you have to resolve the collision by moving the object. You have two options here:

  • Move the object back to its old position, by applying the opposite of the velocity to cancel the movement as soon as you detect a collision. Pros: extremely easy to implement. If it doesn't affect your game play go with this option. Cons: This will prevent the object from moving in any direction that would cause a collision (so you won't be able to slide along a wall for example).
  • Find from where the object is and resolve the collision accordingly. For example, if the object came from the left and collided on the left side of the wall, you would simply move the object just to the left of the wall. By repeating this to all the sides of the rectangles, the object would be allowed to keep moving towards its desired velocity but would still avoid collisions.

Implementation of second option

Here I'll assume that the velocity represents the direction in which the object is going (basically that you are not changing the velocity between the object's position change and the collision check). I'll also assume that your origin is positioned at the top-left of the image (so when moving the object to resolve the collision I'll position the top-left corner).

Here is how I would do:

if (objRect.Intersects(wallRect)) // If there is a collision
{
    Vector2 newPos = obj.Position;

    if (obj.Velocity.X > 0) // object came from the left
        newPos.X = wallRect.Left - objRect.Width;
    else if (obj.Velocity.X < 0) // object came from the right
        newPos.X = wallRect.Right;
    if (obj.Velocity.Y > 0) // object came from the top
        newPos.Y = wallRect.Top - objRect.Height;
    else if (obj.Velocity.Y < 0) // object came from the bottom
        newPos.Y = wallRect.Bottom;

    obj.Position = newPos;
}

You could also use the old object's position to find where the object is from, but using the velocity is simpler in this case.

share|improve this answer
    
Okay, so basically it's stuck in the wall and the collision is continuing. How would I go about resolving this though? –  Jopo Jun 1 '11 at 3:20
    
Was editing it as you asked. Would you like some code samples to show how both options would be implemented? –  Jesse Emond Jun 1 '11 at 3:24
    
I tried implementing the first one earlier by implementing a vector called a direction which is a normalized vector with left or right depending on key pressed, then I multiplied this by the velocity when collision was detected. This worked on the most part, but it only seems to work on one side of the rectangle (the right side?). For the second one, I would much appreciate a code sample as I've heard a lot about this but haven't seen any concrete implementations. –  Jopo Jun 1 '11 at 3:28
1  
Your first option should be an example of what not to do. Any game with that type of collision detection, I would consider defective. –  AttackingHobo Jun 1 '11 at 3:40
1  
Why is this answer not accepted if you managed to implement the given method and it worked? –  Jonathan Connell Jun 1 '11 at 8:56

You can do this in various ways.

One method is storing the previous position of the Rectangle every frame. So, when your rectangles Intersects, just set the object position to the older one that not collided. This method is not the best, because if the Rectangle velocity is high, you may see the reposition that you made via code.

Another method is testing the collision with a Raycast, so you can preview a collision before it ever happens.

Take a look at msdn for documentation for Raycast collision, and you'll be able to do that.

share|improve this answer

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.