2
\$\begingroup\$

Repost from my question on stack overflow, didnt know this site existed.

I have a 2d platformer and I need help with collision. To show you my current collision system, here is picture: http://i.imgur.com/romKF.png

Top picture is how game looks normally, bottom picture shows highlighted collision rectangles. Black ones are horizontal (If player rectangle intersects them, move player on Y axis), blue are vertical (move player on the X axis) and red are corners.

I've implemented corner rectangles, after bit of testing after I found out, that when I had black and blue overlapping each other, this happened: Player jumped and intersected both rectangles at once, game would recognize that and resolve both intersection at the same time, cause the player to spaz around the map and ending up in a another rectangle, which would then cause another intesection and resolution until the chain reaction stopped, and player would end up somewhere where he should not have been.

So I added corner rectangles, they should resolve this situation like this: if player hits corner from the bottom, act like horizotal rectangle, if he hits from side, act like vertical.

Thing is, I have no idea how to make them work like that.

Here is my code so far:

        if (InputHandler.KeyDown(Keys.W))
        {
            player.MoveUp();
            Parallel.For(0, horizontalPlayerCollisionRectangles.Count, i =>
            {
              if (player.PlayerRectangleInWorld.Intersects(horizontalPlayerCollisionRectangles[i]))
                {
                    player.PlayerPositionY = horizontalPlayerCollisionRectangles[i].Y + horizontalPlayerCollisionRectangles[i].Height;
                }
            }); 
        }

        if (InputHandler.KeyDown(Keys.D))
        {
            player.MoveRight();
            Parallel.For(0, verticalPlayerCollisionRectangles.Count, i =>
                {
                    if (player.PlayerRectangleInWorld.Intersects(verticalPlayerCollisionRectangles[i]))
                    {
                        player.PlayerPositionX = verticalPlayerCollisionRectangles[i].X - player.PlayerRectangleInWorld.Width;
                    }
                });
        }

        if (InputHandler.KeyDown(Keys.A))
        {
            player.MoveLeft();
            Parallel.For(0, verticalPlayerCollisionRectangles.Count, i =>
            {
                if (player.PlayerRectangleInWorld.Intersects(verticalPlayerCollisionRectangles[i]))
                {
                    player.PlayerPositionX = verticalPlayerCollisionRectangles[i].X + verticalPlayerCollisionRectangles[i].Width;
                }
            });
        }

        if (player.Gravity)
        {
            Parallel.For(0, horizontalPlayerCollisionRectangles.Count, i =>
            {
                if (player.PlayerRectangleInWorld.Intersects(horizontalPlayerCollisionRectangles[i]))
                {
                    player.PlayerPositionY = horizontalPlayerCollisionRectangles[i].Y - player.PlayerRectangleInWorld.Height;
                }
            }); 
        }

Its pretty simple. Now that I think about it, my system is flawed, so thats why I'm asking this question. How to make collision work using collision rectangles?

P.S. I can't use any physics engine like Farseer, it's a school graduation project and I have to code as much as possible by myself.

\$\endgroup\$

1 Answer 1

4
\$\begingroup\$

You're really close to the answer already. What you want to do is implement all collision rectangles the same way and your idea for "corner rectangles" is pretty much that.

Here's a high level look at what you need to do.

  1. In your collision processing you need to get a list of all rectangles that your player is definitely colliding with.
  2. As you loop through this list you need to test the intersection of the player and each rectangle. This intersection will give you x and y values.
  3. Compare x and y. Whichever value is smaller is the axis you want to resolve along. That is, if x < y, adjust your player's position along the x axis. If y < x, adjust the player along the y axis.
  4. Loop until done.

Since you're using XNA you can check out the Platformer Code Sample on App Hub. I believe the relevant code is in the HandleCollision method in the Player class. This is a working example of what I outlined above.

Metanet also has two really great tutorials on 2D collisions.

  1. Tutorial A
  2. Tutorial B
\$\endgroup\$
0

You must log in to answer this question.

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