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 have been racking my brain trying to figure out a problem I am having with physics and basic AABB collision response. I am fairly close as the physics are mostly right. Gravity feels good and movement is solid. The issue I am running into is that when I land on the test block in my project, I can jump off of it most of the time. If I repeatedly jump in place, I will eventually get stuck one or two pixels below the surface of the test block.

If I try to jump, I can become free of the other block, but it will happen again a few jumps later. I feel like I am missing something really obvious with this. I have two functions that support the detection and function to return a vector for the overlap of the two rectangle bounding boxes. I have a single update method that is processing the physics and collision for the entity.

I feel like I am missing something very simple, like an ordering of the physics vs. collision response handling. Any thoughts or help can be appreciated. I apologize for the format of the code, tis prototype code mostly.

The collision detection function:

public static bool Collides(Rectangle source, Rectangle target)
    {
        if (source.Right < target.Left ||
            source.Bottom < target.Top ||
            source.Left > target.Right ||
            source.Top > target.Bottom)
        {
            return false;
        }

        return true;
    }

The overlap function:

public static Vector2 GetMinimumTranslation(Rectangle source, Rectangle target)
    {
        Vector2 mtd = new Vector2();

        Vector2 amin = source.Min();
        Vector2 amax = source.Max();
        Vector2 bmin = target.Min();
        Vector2 bmax = target.Max();

        float left = (bmin.X - amax.X);
        float right = (bmax.X - amin.X);
        float top = (bmin.Y - amax.Y);
        float bottom = (bmax.Y - amin.Y);

        if (left > 0 || right < 0) return Vector2.Zero;
        if (top > 0 || bottom < 0) return Vector2.Zero;

        if (Math.Abs(left) < right)
            mtd.X = left;
        else
            mtd.X = right;

        if (Math.Abs(top) < bottom)
            mtd.Y = top;
        else
            mtd.Y = bottom;

        // 0 the axis with the largest mtd value.
        if (Math.Abs(mtd.X) < Math.Abs(mtd.Y))
            mtd.Y = 0;
        else
            mtd.X = 0;

        return mtd;
    }

The update routine (gravity = 0.001f, jumpHeight = 0.35f, moveAmount = 0.15f):

public void Update(GameTime gameTime)
    {
        Acceleration.Y = gravity;
        Position += new Vector2((float)(movement * moveAmount * gameTime.ElapsedGameTime.TotalMilliseconds), (float)(Velocity.Y * gameTime.ElapsedGameTime.TotalMilliseconds));
        Velocity.Y += Acceleration.Y;

        Vector2 previousPosition = new Vector2((int)Position.X, (int)Position.Y);

        KeyboardState keyboard = Keyboard.GetState();
        movement = 0;

        if (keyboard.IsKeyDown(Keys.Left))
        {
            movement -= 1;
        }

        if (keyboard.IsKeyDown(Keys.Right))
        {
            movement += 1;
        }



        if (Position.Y + 16 > GameClass.Instance.GraphicsDevice.Viewport.Height)
        {
            Velocity.Y = 0;
            Position = new Vector2(Position.X, GameClass.Instance.GraphicsDevice.Viewport.Height - 16);
            IsOnSurface = true;
        }




        if (Collision.Collides(BoundingBox, GameClass.Instance.block.BoundingBox))
        {
            Vector2 mtd = Collision.GetMinimumTranslation(BoundingBox, GameClass.Instance.block.BoundingBox);

            Position += mtd;

            Velocity.Y = 0;
            IsOnSurface = true;
        }

        if (keyboard.IsKeyDown(Keys.Space) && !previousKeyboard.IsKeyDown(Keys.Space))
        {
            if (IsOnSurface)
            {
                Velocity.Y = -jumpHeight;
                IsOnSurface = false;
            }
        }




        previousKeyboard = keyboard;
    }

This is also a full download to the project. https://www.box.com/s/3rkdtbso3xgfgc2asawy

P.S. I know that I could do this with the XNA Platformer Starter Kit algo, but it has some deep flaws that I am going to try to live without. I'd rather go the route of collision response via an overlay function.

Thanks for any and all insight!

share|improve this question
add comment

1 Answer

I have found the solution myself.

Basically, I reordered to have all input, velocity adjustments and position adjustments before the collision detection and response correction. Once I did that, it was able to correct my position appropriately. I had my jump handling at the end of the update, and I think that was interfering with collision response adjustments. I also quit applying gravity unless I wasn't colliding with anything, or if I was colliding, only apply gravity if it wasn't on the Y axis.

I am not jumping about with zero sticking!

share|improve this answer
add comment

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.