2
\$\begingroup\$

I posted this question two weeks ago: 2D platformer corner collision and I implemented NoobsArePeople2's solution.

Problem is, when player intersects two rectangles that are inside each other, he starts jittering. I don't know how to describe it so I made a video: http://www.youtube.com/watch?v=2AYUGeuxM0c

In the first 4 or so seconds, you can see that when he collides with two rectangles that arent in each other or touching each other, everything works fine, but in the rest of the video, you can see that when player touches side, he starts to jitter (please note that because of fraps, my game was running at quarter of FPS I normaly have, so without fraps the jitter is much faster)

To give you idea how my collision rectangles look now, here is debug mode (each rectangle is randomly colored) enter image description here

I have couple of algortihms in place that merge rectangles into one (still need to do some work on that), but some simply cannot be merged. One example is the C object on the right. Right now it is made of 7 rectangles (will be 3 after I complete my algorithm) and when player slides on side of it, he starts to jitter.

I suspect problem is in my gravity, but Im not sure. I've spent 5 days on trying to fix this and Im lost.

Heres my code (slighty modified from platformer sample):

        for (int i = 0; i < playerCollisionRectangles.Count; i++)
        {
            Vector2 depth = Collision.GetIntersectionDepth(player.PlayerRectangleInWorld, playerCollisionRectangles[i]);
            if (depth != Vector2.Zero)
            {
                float absDepthX = Math.Abs(depth.X);
                float absDepthY = Math.Abs(depth.Y);

                // Resolve the collision along the shallow axis.
                if (absDepthY < absDepthX)
                {
                    // Resolve the collision along the Y axis.
                    player.PlayerPositionY += Convert.ToInt32(depth.Y);
                }
                else  
                {
                    // Resolve the collision along the X axis.
                    player.PlayerPositionX += Convert.ToInt32(depth.X);
                }
            }
        }

And here is my gravity code (very very simple):

        if (Gravity)
        {
            //for camera
            position.Y += 2;
            //position in world
            playerPositionY += 2;
        }

And lastly here is one of my methods to move player (i have similiar methods to move him left and up):

    public void MoveRight()
    {
        animate.Enabled = true;
        animate.Row = 0;
        position.X += speed;
        playerPositionX += speed;
    }
\$\endgroup\$
6
  • \$\begingroup\$ In what order are you handling input, applying gravity and doing collision detection? Should be in that order. \$\endgroup\$ Jan 3, 2012 at 16:08
  • \$\begingroup\$ And when you change player.PlayerPositionX/Y inside the collision code, is the player.PlayerRectangleInWorld reflecting the change too? \$\endgroup\$ Jan 3, 2012 at 16:11
  • \$\begingroup\$ Yes to both of those questions. \$\endgroup\$
    – isklenar
    Jan 3, 2012 at 16:32
  • \$\begingroup\$ Hmm, and if you suspect gravity, have you tried disabling it to verify if it still occurs? \$\endgroup\$ Jan 3, 2012 at 16:40
  • \$\begingroup\$ Just tried it, problem still persist. \$\endgroup\$
    – isklenar
    Jan 3, 2012 at 16:49

1 Answer 1

1
\$\begingroup\$

I think the problem is that when you are iterating through your collisions (playerCollisionRectangles) -- you are adjusting the position of your player more than once. This would explain the correct behavior when you are passing over single rectangles. When you are passing over more than one rectangle, the depth correction is being fired multiple times, causing jitter.

\$\endgroup\$
4
  • \$\begingroup\$ That was it. All I had to add was break; to stop the for cycle. \$\endgroup\$
    – isklenar
    Jan 3, 2012 at 17:45
  • \$\begingroup\$ Congrats on fixing it ;) \$\endgroup\$
    – jgallant
    Jan 3, 2012 at 18:29
  • \$\begingroup\$ This is a bit puzzling. The original platformer sample iterates over all colliding blocks without jitter - in fact it does so purposely in order to resolve multiple collisions. And even though you were adjusting the position more than once, these adjustments were all done in the same update iteration so the played would never see any of the intermediate state. My gut instinct can't help but think that breaking early might turn up causing problems for other corner cases where the player needs to be pushed out of more than one colliding block. But I still can't figure out what's different. \$\endgroup\$ Jan 3, 2012 at 19:38
  • \$\begingroup\$ I think what needs to be done, is verify if there is still a collision after the player's position has been adjusted. If there is, then continue processing the collisions and if not, then you can break out. \$\endgroup\$
    – jgallant
    Jan 3, 2012 at 20:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .