3
\$\begingroup\$

Everytime I have coded "working" collision, I always went about it very haphazardly and unstructured. If I use Axis Aligned, or Verlet, Or Euler, any or all of these theories, my problems always lie in the edge cases. Let me invent a scenario to better explain my question.

Imagine a 2D game, let's use Mario as the best example. So there is gravity, there is acceleration and friction. If the world is being loaded as all individual, let's say 32 x 32, tiles, while the player is moving along the ground, there will always be that edge case of when he happens to be in the dead center of both tiles, and collision ends up being checked on both tiles below him and of course he gets moved based on both tiles' positions.

So in that case, I assume I would only want to be checking top block collision (bottom of player) only, and not side collisions, but then when I'm jumping onto a tile, or block, I know I want to check bottom player collision, so I can land, but that doesn't stand for anytime the player is in the air right? Cause what if I'm falling/jumping, and I hit the side of a block or wall, I want to check side collision. And then what if I hit the side of one block, but in that frame of collision when the player overlapped the tiles, he also got into the top of one of the tiles and now gets his y position moved because of it.

So the tl;dr version of my rambling is...

What's the most sensible way to structure collision? Totally case specific, i.e. only check specific collisions dependant on surrounding tiles, or the movement of the player?

Or is there a broad way to keep all collisions being checked (top, sides and bottom of player) and deal with the edge cases as well?

Also this isn't language specific, I'm speaking totally in generics. Any code examples are welcome. (Any language)

Thanks. (Hope my rambling isn't too convoluted and it makes sense. ><

\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

Here's how I've done it in the past (for AABB rectangle sprites):

  • Find the position the player would be this frame after a position update.
  • Create a rectangle at that position the player will be at and check that rectangle against all other rectangles the player could collide with (preferably only the nearby ones, for efficiency).
  • For any overlaps found, find how far the overlap is from each side of the rectangle. For example, maybe the players sprite is overlapping another sprite such that two sides of the other are overlapping.

enter image description here

In the image here you can see the overlap distances are 5 and 7. From this you can create determine how far to push the player so the they will not be overlapping any longer, you would move the player up 5 units and over 7 units.

The tricky part can be when you're overlapping multiple squares at once though, if you resolve them all one at a time, pushing out of one box can push you into another. To solve this, combine all the results from each rectangle into a single position change, and once you have all of those results you'll know the final position to move the player to this frame.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Your example would always resolve the player to be at the corner. You'd have to figure out the Time of Impact (TOI) for both x and y directions and then for whichever one hits last, figure out the value based on the first one's TOI. So you'd get the position as it was when it first collided. \$\endgroup\$ Commented Feb 9, 2012 at 12:22
  • \$\begingroup\$ +1. Yes including TOI in the calculations would definitely increase the accuracy of something like this, moreso at lower framerates, at a high enough framerate the TOI becomes closer to zero and affects the collision less, but including TOI means you don't have to worry as much about issues during framerate fluctuation. Additionally by calculating TOI you will often find you only need to get pushed one way instead of combining two results, depending on how many sprites your player is overlapping. \$\endgroup\$
    – Nic Foster
    Commented Feb 9, 2012 at 15:30
1
\$\begingroup\$
  1. If differentiating collision with bottom (stops falling) and sides (stops movement) is a problem, do them separately. If you check sides, and push, before starting to check bottom, you will be out of the sides by the time bottom is checked. Also, you can do friction and collision checks separately.

  2. What I do is use a rectangle intersect method similar to Nic's. I have a small area around the sprite representing "space where the sprite can go", and if any colliding objects overlap that boundary, the boundary is shrunk. Then the sprite is locked to the boundary. It seems simple enough.

  3. http://info.sonicretro.org/Sonic_Physics_Guide has a detailed explanation of a sophisticated collision system.

  4. It is impossible for an object to be "above two tiles"- its position is a vector, and is above only one tile, unless tiles overlap.

\$\endgroup\$

You must log in to answer this question.

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