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.

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?

share|improve this question

1 Answer 1

up vote 1 down vote accepted

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.

share|improve this answer
    
This was exactly the trouble. I've now implemented a (mostly) working solution with the advice you gave. There are a few bugs I need to work out but this is definitely the direction I needed to go in. Thanks! –  SpartanDonut Jan 31 '12 at 3:42

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.