Sunday, December 4, 2016

xna - Stuck in Wall after rectangle bounding box collision


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?



Answer



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.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...