Collision reaction in a 2D side-scroller game similar to "Mario"

Rob picture Rob · Jul 13, 2011 · Viewed 10.9k times · Source

This has been greatly bothering me in the past few weeks. In this time I've been researching online, even reading books in the Computers section at Borders to try to find an answer, but I haven't had much luck.

I programmed a 2D level editor for side-scroller video games. Now I want to turn it into a game where I have a player who can run and jump to explore the level, similar to "Mario".

The thing that is really giving me trouble is the collision response (not detection: I already know how to tell if two blocks are colliding). Here are some scenarios that I am going to illustrate so that you can see my problems (the shaded blocks are the ground, the arrow is the velocity vector of the player, the dashed lines are the projected path of the player).

See this collision response scenarios image:

example http://dl.dropbox.com/u/12556943/collision_detection.jpg

Assume that the velocity vectors in scenarios (1) and (2) are equal (same direction and magnitude). Yet, in scenario (1), the player is hitting the side of the block, and in scenario (2), the player is landing on top of the block. This allows me to conclude that determining the collision response is dependent not only on the velocity vector of the player, but also the player's relative position to the colliding block. This leads to my first question: knowing the velocity vector and the relative position of the player, how can I determine from which direction (either left side, right side, top, or bottom) the player is colliding with the block?

Another problem that I'm having is how to determine the collision response if the player collides with multiple blocks in the same frame. For instance, assume that in scenario (3), the player collides with both of those blocks at the same time. I'm assuming that I'm going to have to loop through each block that the player is colliding with and adjust the reaction accordingly from each block. To sum it up, this is my second question: how do I handle collision response if the player collides with multiple blocks?

Notice that I never revealed the language that I'm programming in; this is because I'd prefer for you to not know (nothing personal, though :] ). I'm more interested in pseudo-code than to see language-specific code.

Thanks!

Answer

chaosTechnician picture chaosTechnician · Jul 14, 2011

I think the way XNA's example platform game handles collisions could work well for you. I posted this answer to a very similar question elsewhere on Stack Overflow but will relay it here as well.

  1. After applying movement, check for and resolve collisions.
  2. Determine the tiles the player overlaps based on the player's bounding box.
  3. Iterate through all of those tiles doing the following: (it's usually not very many unless your player is huge compared to your world tiles)
    1. If the tile being checked isn't passable:
      1. Determine how far on the X and Y axes the player is overlapping the non-passable tile
      2. Resolve collision by moving the player out of that tile only on the shallow axis (whichever axis is least penetrated)
        • For example, if Y is the shallow axis and the collision is below, shift the player up to no longer overlap that tile.
        • Something like this: if(abs(overlap.y) < abs(overlap.x)) { position.y += overlap.y; } else { position.x += overlap.x; }
      3. Update the bounding box's position based on the player's new position
      4. Move on to the next tile...
    2. If the tile being checked is passable, do nothing
  4. If it's possible that resolving a collision could move the player into another collision, you may want to run through the above algorithm a second time. Or redesign your level.

The XNA version of this logic is in player.cs in the HandleCollisions() function if you are interested in grabbing their code to see what they specifically do there.