Wednesday, March 9, 2016

movement - How can I determine which direction a 2D collision is occurring from?


The problem is as follows:


Think 2D Zelda (Links Awakening, A Link to the Past) style movement where you can run into walls from any of the four cardinal directions, or basically up, down, left, and right. The difference between my movement and these games is I want to allow for diagonal movement as well. When the player collides with a wall on the left, for example, if he is pushing left and up I want him to stop moving left but continue moving up. The problem I am having is my code currently detects the collision as both an upwards and a left collision so the player simply stops. What is the approach I should take to remedy this?


        bool canCollideLeft = false;
bool canCollideRight = false;
bool canCollideUp = false;
bool canCollideDown = false;

if (HeroRect.Left > OldHeroRect.Left)
{

canCollideLeft = false;
canCollideRight = true;
}

if (HeroRect.Left < OldHeroRect.Left)
{
canCollideLeft = true;
canCollideRight = false;
}


if (HeroRect.Bottom > OldHeroRect.Bottom)
{
canCollideUp = false;
canCollideDown = true;
}

if (HeroRect.Bottom < OldHeroRect.Bottom)
{
canCollideUp = true;
canCollideDown = false;

}


foreach (RectangleItemProperties rectangle in CollisionRectangles)
{
Rectangle CollisionRect = new Rectangle((int)rectangle.Position.X, (int)rectangle.Position.Y, (int)Math.Abs(rectangle.Width), (int)Math.Abs(rectangle.Height));

if (HeroRect.Intersects(CollisionRect))
{
if (canCollideDown && HeroRect.Bottom >= CollisionRect.Top && HeroRect.Bottom <= CollisionRect.Bottom)

{
hero.position.Y = OldHeroRect.Location.Y;
}

if (canCollideUp && HeroRect.Top >= CollisionRect.Top && HeroRect.Top <= CollisionRect.Bottom)
{
hero.position.Y = OldHeroRect.Location.Y;
}

if (canCollideLeft && HeroRect.Left <= CollisionRect.Right && HeroRect.Left >= CollisionRect.Left)

{
hero.position.X = OldHeroRect.Location.X ; ;
}

if (canCollideRight && HeroRect.Right >= CollisionRect.Left && HeroRect.Right <= CollisionRect.Right )
{
hero.position.X = OldHeroRect.Location.X;
}
}
}


In summary the code compares the old position with the new position to see which direction we have moved and checks for a potential collision there. So if we move up and to the left, canCollideLeft and canCollideUp will be true. I am pretty sure this is where my problem lies and I need to better check which direction I am colliding from.


Any thoughts or insight?



Answer



From your code it seems you're checking both directions at the same time, but for proper movement it's better to check each direction individually. You can google around for Axis Aligned Bounding Boxes to find various methods of doing rectangle collision.


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...