7
\$\begingroup\$

I've basically asked this question before, and I know it's been asked probably a billion times, but I still can't seem to do it. All I want to know is how I should go about doing basic 4-way, rectangular collisions (up, down, left, right). I have been searching for an answer on and off for months and I can't seem to find it. All I need to know is some basic code examples (in Java, preferably) for how I would do this. I've tried a few different methods before, but they just don't seem to work (I can get certain sides to work, but not all of them at the same time). I'm making this game entirely from scratch and I'm using libgdx as my framework. I don't want to use Box2D or any other engine. Thanks in advance to anyone who will help me!

tl;dr: 4 way collisions, how do they work?

\$\endgroup\$

4 Answers 4

4
\$\begingroup\$

The XNA 2D Platformer example has a pretty straight forward algorithm it uses for collision detection and resolution. Here's an answer I've given over on Stack Overflow a couple of times. It's a language agnostic approach that can likely be adjusted to fit your actual needs. If you want to see their actual code (though it's in C#), it is in player.cs in the HandleCollisions() function.

  1. After applying movement, check for and resolve collisions by doing the following.
  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.
\$\endgroup\$
3
  • \$\begingroup\$ I actually saw this post before and I actually tried this out. It didn't necessarily work (certain sides collided better than others), but I didn't do it EXACTLY the way you did (I didn't think about adding the overlap length back to the position, that's brilliant), so I'm going to try it out soon and see if it works! \$\endgroup\$
    – TheGag96
    Commented Oct 12, 2011 at 0:56
  • \$\begingroup\$ Wait, could you Pastebin the contents of player.cs for me? I honestly don't feel like getting the XNA Kit, especially when this will be the only time I use it and I don't program in C#. Thanks! \$\endgroup\$
    – TheGag96
    Commented Oct 13, 2011 at 1:55
  • \$\begingroup\$ Google is your friend. All the code for that particular example is available here without the need to install XNA: create.msdn.com/en-US/education/catalog/sample/platformer \$\endgroup\$ Commented Oct 13, 2011 at 2:27
2
\$\begingroup\$

Okay language agnostic, I much prefer my approach to the shallow penetration test.

Things You Need

  1. You need some way to store previous positions of your objects
  2. You need a way to detect and store all current objects you're colliding with

How It Works

First, you need to find the object with the nearest wall- in a tile system this is a simple check for the tile with the nearest center. When I did this I sorted my objects from closest to farthest.

Next, you run this routine on it:

if (we are colliding){
 if (mypreviousdown <= theirpreviousup){ //if I was previously above them
  move upwards() //probably set our position to their position - our height
  set our y velocity = their y velocity() // for moving platforms
  //optional
  add their velocity to our position() // for sticky platforms
  // end optional
 }
 if (mypreviousup >= theirpreviousdown){ //if I was previously below them
  move downwards()
  set our y velocity = their y velocity() // for moving platforms
  //optional
  add their velocity to our position() // for sticky platforms
  // end optional
 }
}

if (we are still colliding){
 if (mypreviousright <= theirpreviousleft){
  move to the left()
  set our x velocity = their x velocity
 }
 if (mypreviousleft >= theirpreviousright){
  move to the right()
  set our y velocity = their y velocity
 } 
}

Considerations

This system works fantastically well, and I have yet to see any bugs- unless you're moving fast enough to move to the other side of the object, but if you're not, this works great.

One thing you may want to consider is adding some functionality to slip around edges or go up steps, it will add some good gameplay mechanics to your game.

Another thing you may want to add is a way to detect which side is currently colliding at any given time(for things like jumping and such)

You may also consider a custom event system, it's been a great help to my game programming lately.

\$\endgroup\$
0
1
\$\begingroup\$

Simply said: on each frame for each moved rectangle, check if it intersects with any other rectangle if so, don't update the position. There are numerous ways to optimize this using spatial partitioning techniques. But what are you having trouble with precisely?

Note that http://code.google.com/p/libgdx/source/browse/trunk/gdx/src/com/badlogic/gdx/math/Rectangle.java says that the rectangle is defined by it's most bottom-left point, while it is more common to use the top-left point so take that in to account when using intersection code snippets and tutorials.

\$\endgroup\$
0
\$\begingroup\$

One way: You might look at Box2D source code, or collison source code in Java.

Other way: I understood logic behind collisions from article about collision detection on Flipcode. I took a piece of paper, wrote down and derived what he wrote about. Then I was able to code it. Math helped me, it might do for You too. (I believe that Youry rectangular 4way is on the beginning)

\$\endgroup\$

You must log in to answer this question.

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