Tiled Level Collision Help

I have a tiled level, which is expressed as:


int[][] level1 = {{1,0,0,0,0,0,1,1},
                       {1,0,0,0,0,0,0,1};

etc

I then render the tiles with code from mattheus :slight_smile:


 // Render the Level
	  public void renderTiles(Graphics g) {
		   // Iterate through all tiles:
			for (int y = 0; y < level1.length; y++) {
			      for (int x = 0; x < level1[y].length; x++) {
		         renderTile(x, y, level1[y][x], g);
		      }
		   }
		}
	  public void renderTile(int x, int y, int tileID, Graphics g) {
			  switch (tileID) {
			  // don't forget the breaks! :)
			  case 0: g.setColor(Color.BLACK); g.fillRect(x * 16, y * 16, 16, 16); break; 
			  case 1: g.setColor(Color.GREEN); g.fillRect(x * 16, y * 16, 16, 16); break;
			  }
		}

My player info:


int playerX = 16, playerY = 16;

how can I check collision between the player and the tiles which are 1?

I’ve tried, some different methods:
[x] Surround wall tiles in a Rectangle each the player in a Rectangle and check for collision between them. But I needed to use an array of Rectangles, and I hit the problem: i had to define what [] is for the .intersects() method.
[x] I tried checking if playerX and playerY were ā€˜Beside’ a wall so that it wouldn’t allow them to move, again, I think I need to define what tile I’m comparing them to.

Anyone have any suggestions I can try?

If you assume that the player is a rectangle, it is pretty easy to check collisions within a grid. Just get the grid index from the (minX, minY) and (maxX, maxY) points for the player and iterate over those cells to check if they are occupied in your tile map.

Also, when the player moves you also want to perform several checks that the player doesn’t move into an occupied cell in the next tick.
Also, if you allow diagonal movement, you would like to know if the player can move in one direction (either x or y) only to avoid that it just stops when diagonally moving into a wall.

You don’t need to specify rectangles for each cell. You just need to know the total grid size, it’s start position and the number of cells in each direction. Then you can calculate all the rectangles with some very simple math.

First, what do you mean by minX minY and maxX and maxY of player? Would that be 0,0 and say 320,240.

any tips on how to do the Rectangles?

and what math? I’m completely confuzzled

Is the player a point or has it some width or height? If it is a point then you can just ignore the minX, minY etc and just use playerX and playerY instead.

Is the player supposed to move in steps of whole cells or can it move a fraction of a cell? If it can just move in whole grid cells you can just perform a simple array[playerY][playerX] (with bounds checking). If it can move within fractions of cells, the player can overlap several cells at the same time. You need to check what cells that the player overlaps and then you need to know the size of the cells.

Here is some code where I assume that the level starts at position (0, 0) and the player position is at center of the player rectangle.


int startCellX = (int) Math.floor((playerX - playerWidth * 0.5) / cellWidth);
int startCellY = (int) Math.floor((playerY - playerHeight * 0.5) / cellHeight);
int endCellX = (int) Math.ceil((playerX + playerWidth * 0.5) / cellWidth);
int endCellY = (int) Math.ceil((playerY + playerHeight * 0.5) / cellHeight);

for (int i=startCellX; i<=endCellX; i++) {
  for (int j=startCellY; j<=endCellY; j++) {
    // Check if level1[j][i] is occupied here, if so, the player intersects something
  }
}


You also have to add some checks for not referencing something outside the array.

It moves one cell which is 16*16, but I haven’t really done a cell if you know what I mean, just the level1[][], ahhh! I’m so confused!

I can’t get this to work! It’s probably something extremely easy, I’m just missing it!

My character now jumps several spaces, regardless of where it is.
I’m using a simple Graphics package because that is what I’m restricted too.
I need to try and have it that the character can move if its on an ā€˜0’ tile but it can’t move onto a 1 tile.
i’ve tried trying to predict what the tiles around the character are, but I can’t get that to work either :frowning:

sorrry, I’ve been trying to fix this for the last couple of days, and haven’t had a clue.

is there anyway I could do


int[][] playerPos;

and then use it to define the player position?
but how can i use it for rendering the image according to the


playerPos[y][x]

It’s a bit too hard-coded to just check if the tile is 0 or 1, if you want to have several types of tiles. If you only need 2 types of tiles (walls and not walls) then it is fine.

If you have more types of tiles, like grass, forest (makes player move slower or leaves could fly around the player), or water (stops the player unless his name is Jesus) or whatever, then I’d recommend a Tile-class, which has an int ID (which refers to the number used in the map[][]), and an int type to recognize which kind of tile it is, and lastly a boolean passable indicating if it can be traversed at all.

Using simple rectangles to check for collisions is fine, but I believe there’s an easier method, which also makes it much easier to control what to do, depending on which side of the player is colliding with a tile. Not to mention the freedom for precision, in that you can put the points as close to the actual player-part of your image, if he doesn’t fill out the entire image.

What I did for my game, was to check 8 points around the player (see image below), and react if one of these points are within a tile that cannot be traversed. If any of the 4 top/bottom points are within a tile, I move the player back to his previous Y-position (which I save in a variable every update). If any of the 4 left/right points are within a tile, I move the player back to his previous X-position (which I save in a variable every update).

It is important to do the X and Y separately, or your player will get stuck in weird ways, meaning you can’t be walking left into a wall and still move upwards or downwards along it.

http://img534.imageshack.us/img534/3953/collisionthingy.jpg

This is what I used in my very first game, and it works perfectly. (See for yourself.

Extremely simplified code to move the player. Use whatever you’d like:


    public void movePlayer(){
    	if(keys[KeyEvent.VK_UP]){
    		player.setPlayerPositionY(player.getPlayerPositionY()-3);
    	}
    	if(keys[KeyEvent.VK_DOWN]){
    		player.setPlayerPositionY(player.getPlayerPositionY()+3);
    	}
    	if(keys[KeyEvent.VK_LEFT]){
    		player.setPlayerPositionX(player.getPlayerPositionX()-3);
    	}
    	if(keys[KeyEvent.VK_RIGHT]){
    		player.setPlayerPositionX(player.getPlayerPositionX()+3);
    	}
    }

When the player has been moved, we do the collision-checking.
Code to check all points for collisions and reacting to them (the offsets for the points are hardcoded after the size of my player image; the playerPosition is the dead center of the player image in my game):


    public void checkCollisionsAroundPlayer(){
    	int tileCoordX = player.getPlayerPositionX();
    	int tileCoordY = player.getPlayerPositionY();
    	Point upRight = new Point(), upLeft = new Point(), rightTop = new Point(), rightBot = new Point(), leftTop = new Point(), leftBot = new Point(), downRight = new Point(), downLeft = new Point();
    	
    	upRight.setLocation(tileCoordX+9,tileCoordY-13);
    	upLeft.setLocation(tileCoordX-9,tileCoordY-13);
    	rightTop.setLocation(tileCoordX+13,tileCoordY-9);
    	rightBot.setLocation(tileCoordX+13,tileCoordY+9);
    	leftTop.setLocation(tileCoordX-13,tileCoordY-9);
    	leftBot.setLocation(tileCoordX-13,tileCoordY+9);
    	downRight.setLocation(tileCoordX-9,tileCoordY+13);
    	downLeft.setLocation(tileCoordX+9,tileCoordY+13);
    	
    	if(checkCollisionForPoint(upRight) || checkCollisionForPoint(upLeft)){
    		player.setPlayerPositionY(player.getLastY());
    	}
    	if(checkCollisionForPoint(downRight) || checkCollisionForPoint(downLeft)){
    		player.setPlayerPositionY(player.getLastY());
    	}
    	if(checkCollisionForPoint(leftTop) || checkCollisionForPoint(leftBot)){
    		player.setPlayerPositionX(player.getLastX());
    	}
    	if(checkCollisionForPoint(rightTop) || checkCollisionForPoint(rightBot)){
    		player.setPlayerPositionX(player.getLastX());
    	}
    }

Code to check a single point for collisions. The tiles are referenced by their ID in the ground[][], which is looked up in my TileList, which is a list of all loaded Tile-objects. Each Tile-object knows if it is passable:


    public boolean checkTileCollisionsFromMapCoordinates(int tileCoordX, int tileCoordY){
    	boolean collides = false;
    	int tileX = getTilePosX(tileCoordX);
    	int tileY = getTilePosY(tileCoordY);
    	if(!tileList.getTileList().get(map.getGround()[tileY][tileX]).isPassable()) collides = true;
    	
    	return collides;
    }

I understand the points so i’ll try that :slight_smile: thanks for the suggestions. If it helps, I’m not looking for a complex collision system just an extremely simple one, my map is all squares and the character will end up being a circle, so it doesn’t need to be too complicated. Everything i try seems to fail but.

I wrote this: ā€œHow to approach 2D side-scrolling platformer collisions easilyā€
Meant for a platformer, but many of the same points apply. It’ll help you around some devious traps :slight_smile:

Thanks I’ll read through that now :slight_smile:

Thanks for the help everyone, I’ll update you all if I get this working.

I got it working!

I think some people said this already, and with that and by reading through Ultroman’s code, I got a way of doing it formed in my head. Thanks :slight_smile:

I simply let the player walk onto a ā€œwallā€ then check to see if the player is on a ā€œwallā€ by using


if( level1[pY][pX] == 1 )
{
   pX = prevX;
   pY = prevY;
}

I knew something simple would have been what it takes to do it, thanks everyone for helping me out! This took much longer than I had anticipated :slight_smile: