Collision Help 2D Tiles

Hello JGO, I’ve had this weird issue every time I try to program collision into a game lol.

I am trying to implement Collision for Rectangle Vs. Rectangle.
As we all know a rectangle has 4 sides, thus there’s 4 sides to check collision for ;D

My collision works perfect, I just cannot get it to work on ALL 4 SIDES >…<

At the moment I can basically ‘pick’ which 2 sides (top/bottom -or- left/right) of a tile will have active collision areas.

Here is the process of my game:


	public void process() {
		if (canMove) {
			if (up) { /* do stuff... */ }
			if (down) { /* do stuff... */ }
			if (left) { /* do stuff... */ }
			if (right) { /* do stuff... */ }
		}
	}

The above code will result in me being able to slide up / down while moving right / left.
(Collision is being applied properly to the tiles left / right side)

It is vice-verse, if I re-order the code like so:
(Please note the changes between the 2 code snippets)


	public void process() {
		if (canMove) {
			if (left) { /* do stuff... */ }
			if (right) { /* do stuff... */ }
			if (up) { /* do stuff... */ }
			if (down) { /* do stuff... */ }
		}
	}

The above code will result in me being able to slide left / right while moving up / down.
(Collision is being applied properly to the tiles top / bottom side)

Notes: It always favors the last 2 if statements 0_0

This is rather weird 0_0, I’ve tried implementing a Thread which starts prior to the if statements in hopes of running the other collision sides on a whole new ‘scene’ but that still didn’t work >.<

If anyone can help that would be great, if I left out anything needed or you require something more than what I provided :slight_smile: please feel free to ask me for it.

I need help :c
I’m motivated lets figure this out =D

Okay, I’ll try and outline a good method for collision detection.

  1. Create a new position by adding the total velocity to the current position.
  2. Check (currentX, newY) for collisions.
  3. If there is a collision, don’t do anything. If there isn’t, set currentY to newY.
  4. Check (newX, currentY) for collisions.
  5. If there is a collision, don’t do anything. If there isn’t, set currentX to newX.

Hope that helps.

Thanks for the feedback, implementing it now :slight_smile:

Never mind, it didn’t work :c

Thanks for the feedback though

Code?

Tis not a issue with the collision code nor how it’s checked lol.

Like I said ;D it will pick a set of if statements for some reason, maybe I’m not approaching collision correctly <.<


	private void update(int translate_x, int translate_y) {
		translated_x = -translate_x + absX; // player moving right = increase
		translated_y = -translate_y + absY; // player moving up = increase
		if (canMove) {
			if (up) { // up key's pressed
				last_y_move[1] = false;
				last_x_move[0] = false;
				last_x_move[1] = false;
				boolean move = true;
				if (collision_tiles != null) {
					for (int i = 0; i < collision_tiles.length; i++) {
						if (collision_tiles[i] != null) {
							for (Tile t : collision_tiles[i]) {
								if (t != null) {
									if (t.getColor() == 1) { // solid block
										if (new Rectangle(translated_x, translated_y + mapVelY,
												width, height).intersects(t.getRect())) {
											move = false;
										}
									}
								}
							}
						}
					}
				}
				if (move) {
					last_y_move[0] = true;
					getLoader().getWorldRender().mapY += mapVelY;
				}
			}
		}
	}

I am using something like HeroesGraveDev told to keep my character inside of the screen. It is a little buggy, but it might help you to get a better one for yourself. Here is how I do it for now;

float x = body.getLinearVelocity().x; //I get velocities so that when I set the Vector2, I am able to set only x or only y to 0
		float y = body.getLinearVelocity().y;
                //New position is just old position + velocity
		Vector2 newPos = new Vector2(body.getPosition().x + body.getLinearVelocity().x, body.getPosition().y + body.getLinearVelocity().y);
		if (newPos.x < 0 || newPos.x > world.camera.viewportWidth) { 
			// Don't move or return
			body.setLinearVelocity(0, y);
		}
		if (newPos.y < 0 || newPos.y > world.camera.viewportHeight) {
			// Don't move or return
			body.setLinearVelocity(x, 0);

Instead of if (newPos.x < 0 || newPos.x > world.camera.viewportWidth), you could do if (newCharBounds.overlaps(wallBounds))

Like I said, it is buggy for now. It doesn’t go all the way to the border of the screen when the velocity is high :smiley:

Why are you iterating through all the tiles when you check for collisions?

What do you mean why xD

It’s a LinkedList containing collision based & non collision based tiles.

I’m looping through the list, finding the collision based tiles and handling them appropriately lol. :persecutioncomplex:


	if (t.getColor() == 1) { // solid block
		/* Handle teh collision */
	}

Should I add the collision based tiles to a new list to keep my iteration count as low as possible when dealing with collision? ~_^

You know, there’s a way to handle tile-based collisions without iterating.

Simple test in a 1d or 2d map.

Do you mean problematically resolving the collision?
or…?

Floor the position of each corner and test if there is a solid tile there.

What do you mean ~_^?

You only want to check like 4 tiles, left, right, up and down tile, as its impossible for you too collide with a tile 5 tiles away

Thanks for the tip mate :>

I’m in the middle of re-writing the whole project at the moment (Making a Mini_Project for testing) :slight_smile:

This time the player will be restricted to moving + 32pixels in each direction instead of ‘free roaming’ in any direction (Will be easier to do collision)

So basically he’ll be able to move 1 Tile at a time, collision’s 1 area in creating games that’s really held me back so I’ll do it in a way I’m sure will work :slight_smile:

You only need to check for the four tiles if you are moving one step in a direction at once. So in psuedocode,


Tile[] collisionTiles = new Tile[4];

if ( tileExistsUp )
{
    collisionTiles[0] = upTile;
}
if ( tileExistsDown )
{
    collisionTiles[1] = bottomTile;
}
if ( tileExistsLeft )
{
    collisionTiles[2] = leftTile;
}
if ( tileExistsRight )
{
    collisionTiles[3] = rightTile;
}

for ( Tile tile : collisionTiles )
{
    if ( tile != null )
    {
        // process collision here.
    }
}

What mean is, you can calculate which tile to check for collisions by a simple division.

playerpos/tilesize would give you the particular tile to check.

Okay:

Loop through each corner of the entity’s collision box.
Divide and floor by the tile size.
Get the tile at that position.
If the tile is solid, then there is a collision.