[Solved] Odd Collision Issue

Ahoy!

So for a practice project, I decided to slowly build a tile system and really tear apart the collision so that I could understand it all. When doing so, I came across something I just can’t seem to figure out. Here is a photo:

Essentially, the block will get stuck in the wall before stopping, but not every time. The image shows an example along with the X collision handling and position/velocity handling, but it also occurs for the Y direction. What is a better method of collision that will allow me to avoid this?

Here is my getTiles method:

	public void getTiles(int startX, int startY, int endX, int endY){
		Level level = world.getLevel(); //Level has the tile array
		rectPool.freeAll(tiles); //don't know if I need to since its in the player class..
		tiles.clear();  //Clears rectangle array called tiles
		for(int x = startX; x <= endX; x++){ 
			for(int y = startY; y <= endY; y++){
				Tile tile = level.get(x, y); ///grab tile in that spot
				if(tile != null){ //if not null
					Rectangle rect = rectPool.obtain(); //grab rectangle out of pool
					rect.set(tile.getBounds()); //set it to the bounds of the tile
					tiles.add(rect); //add to rectangle array
				}
			}	
		}
	}

Thank you!

  • A

Edit* - The max speed of the player is 5f… in case that is relevant.

Without seeing all your code, and fulling understanding your collision system this is my best guess based on the symptoms:
To me it sounds like you’re moving the entity faster than 1 pixel/cycle and checking for collision at the end of the cycle, so if lets say you’re moving 5 pixels a cycle you may hit the wall and go into it a few pixels before the collision check fires in the same cycle. Thus, you did collide, but now you’re also partially overlapping and trapped.

If I’m right, you should be able to slow down your movement speed and you’ll no longer get stuck.

Collision issues are a pain to debug, because everyone’s code is different. :wink:

Unfortunately, slowing it down didn’t fix the issue, even at 1f! & You’re definitely right with the collision pains.

I was able to fix it by removing the “If bounds overlaps tile” portion… but I don’t understand how that fixed it and if its safe to leave it that way.

for(Rectangle tile : tiles){
        velocity.x = 0;
	break;
}

It doesn’t even use the tile? It just stops player velocity for each tile that exist in the tiles array? How does that even make sense?

Thanks!

  • A

huh. That’s strange. You must have some wonky code somewhere tripping it up. Maybe somewhere else where you’re checking for overlaps that has a return; that should(nt) be firing?

Not that I can see. I understand why it works now though.

1.) Get exact location (startX, startY, endX, endY) and add the tile next to it (depending on direction (or velocity)) to the tile array.
2.) If there is a tile in the array, it stops velocity.

It makes sense but does(nt) need the (Rectangle tile : tiles) loop. Is there anyway to do a “for each item in this array” without needing to use the item? I don’t know if this makes sense.

Well, right now you’re not really even running the loop. You run it once, set velocity.x to 0 and break the loop. So really your entire loop is being ignored.

But I’m not quite following what you mean, there are other ways to write the forloop, but the actual end functionality would be the same.

For example this is (basically) the same;

for (int x = 0; x < tiles.size(); x++)
	tiles.get(x).doSomething();

as:

for (Rectangle tile : tiles)
	tile.doSomething();

You say that “the block will get stuck in the wall before stopping” which makes sense because the velocity is only set to zero once a collision is detected. Nowhere is the position of the player corrected to not be colliding (stuck in the wall), there is only collision detection, no resolution.

Check the space you’re moving to [b]before[b] moving and only move there if it’s actually possible.

Actually, the velocity is added to the position, or something like that. The resolution is within the big block of code. This is technically solved… but not at the same time. I was able to fix it by removing the “if bounds overlaps tile”. I’m using the collision scheme that this uses, essentially : https://github.com/libgdx/libgdx/blob/master/tests/gdx-tests/src/com/badlogic/gdx/tests/superkoalio/SuperKoalio.java