12 Replies - 12238 Views - Last Post: 13 June 2012 - 02:26 PM Rate Topic: -----

#1 SYNYST3R1   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 6
  • Joined: 28-August 11

Java - 2d array Tile map collision

Posted 12 June 2012 - 02:58 PM

How would I go about making certain tiles in my array collide with my player? Like say I want every number 2 in the array to collide. I am reading my array from a txt file if that matters.


Here is my code if needed.

public class Tiles {
    
    Image[] tiles = new Image[3];

    int[][] map = new int[500][500];
    
    Image grass, dirt, mound;
    
    SpriteSheet tileSheet;
    
    int tileWidth = 32;
    int tileHeight = 32;

    public void init() throws IOException, SlickException {
        tileSheet = new SpriteSheet("assets/tiles.png", tileWidth, tileHeight);
        
        grass = tileSheet.getSprite(0, 0);
        dirt = tileSheet.getSprite(7, 7);
        mound = tileSheet.getSprite(2, 6);
        tiles[0] = grass;
        tiles[1] = dirt; 
        tiles[2] = mound;
          
        int x=0, y=0;
	BufferedReader in = new BufferedReader(new FileReader("assets/map.txt"));
	String line;
	while ((line = in.readLine()) != null) {
            String[] values = line.split(",");
	    for (String str : values) {
                int str_int = Integer.parseInt(str);
                map[x][y]=str_int;
                //System.out.print(map[x][y] + " ");
                y=y+1;
            }
	//System.out.println("");
	x=x+1;
        y = 0;
	}
        in.close();
    }
    
    public void update() {
        
    }
    
    public void render(GameContainer gc) {
        for(int x = 0; x < 50; x++) {
            for(int y = 0; y < 50; y ++) {
                int textureIndex = map[y][x];
                Image texture = tiles[textureIndex];
                texture.draw(x*tileWidth,y*tileHeight);
            }
        }
    }
}


I am using the slick2d library. I tried using rectangles, but I'm not sure how I would go through the array and check for just the 2's.

Is This A Good Question/Topic? 0
  • +

Replies To: Java - 2d array Tile map collision

#2 BBeck   User is offline

  • Here to help.
  • member icon


Reputation: 792
  • View blog
  • Posts: 1,886
  • Joined: 24-April 12

Re: Java - 2d array Tile map collision

Posted 12 June 2012 - 06:08 PM

//X,Y = player's position
if (map[x][y] = 2)
{
  //Collision Occured
}



Actually, you "may" want to do "proposed" player position as opposed to actual player position. For example, when the player tries to move to a spot you check if that spot causes a collision and don't allow them to move there if it does, or whatever the collision effect is.

This post has been edited by BBeck: 12 June 2012 - 06:10 PM

Was This Post Helpful? 1
  • +
  • -

#3 SYNYST3R1   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 6
  • Joined: 28-August 11

Re: Java - 2d array Tile map collision

Posted 12 June 2012 - 06:56 PM

View PostBBeck, on 12 June 2012 - 06:08 PM, said:

//X,Y = player's position
if (map[x][y] = 2)
{
  //Collision Occured
}



Actually, you "may" want to do "proposed" player position as opposed to actual player position. For example, when the player tries to move to a spot you check if that spot causes a collision and don't allow them to move there if it does, or whatever the collision effect is.


How exactly would I figure the proposed position? Using the code with just the player position gives me array out of bounds errors. If I can figure your way out this will be a lot simpler than what I was trying before.
Was This Post Helpful? 0
  • +
  • -

#4 SYNYST3R1   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 6
  • Joined: 28-August 11

Re: Java - 2d array Tile map collision

Posted 12 June 2012 - 07:05 PM

I fixed the out of bounds, but I am still not "colliding". I am printing to console when I collide, but it never collides
Was This Post Helpful? 0
  • +
  • -

#5 anonymous26   User is offline

  • D.I.C Lover

Reputation: 2
  • View blog
  • Posts: 3,638
  • Joined: 26-November 10

Re: Java - 2d array Tile map collision

Posted 13 June 2012 - 09:03 AM

View PostBBeck, on 13 June 2012 - 02:08 AM, said:

//X,Y = player's position
if (map[x][y] = 2)
{
  //Collision Occured
}



Actually, you "may" want to do "proposed" player position as opposed to actual player position. For example, when the player tries to move to a spot you check if that spot causes a collision and don't allow them to move there if it does, or whatever the collision effect is.

I don't code in Java, but shouldn't the code be something like:

//X,Y = player's position
if (map[x][y] == 2)
{
  //Collision Occured
}


Where the '=' is replaced with '==' to test equality rather than invoke an assignment?
Was This Post Helpful? 0
  • +
  • -

#6 BBeck   User is offline

  • Here to help.
  • member icon


Reputation: 792
  • View blog
  • Posts: 1,886
  • Joined: 24-April 12

Re: Java - 2d array Tile map collision

Posted 13 June 2012 - 10:22 AM

View PostButchDean, on 13 June 2012 - 09:03 AM, said:

View PostBBeck, on 13 June 2012 - 02:08 AM, said:

//X,Y = player's position
if (map[x][y] = 2)
{
  //Collision Occured
}



Actually, you "may" want to do "proposed" player position as opposed to actual player position. For example, when the player tries to move to a spot you check if that spot causes a collision and don't allow them to move there if it does, or whatever the collision effect is.

I don't code in Java, but shouldn't the code be something like:

//X,Y = player's position
if (map[x][y] == 2)
{
  //Collision Occured
}


Where the '=' is replaced with '==' to test equality rather than invoke an assignment?



Absolutely it should. Dang. I make that mistake all the time. When I was coding regularly in other languages, I used to speak the code outloud as I was programming and I would say "Takes the value of" for "=" instead of saying "equals" just to keep it straight in my mind.

But yes, I wrote a bug. It should be "==".

SYNYST3R1, that could be the problem if you used that exactly as written.

This post has been edited by BBeck: 13 June 2012 - 10:25 AM

Was This Post Helpful? 0
  • +
  • -

#7 BBeck   User is offline

  • Here to help.
  • member icon


Reputation: 792
  • View blog
  • Posts: 1,886
  • Joined: 24-April 12

Re: Java - 2d array Tile map collision

Posted 13 June 2012 - 10:32 AM

View PostSYNYST3R1, on 12 June 2012 - 06:56 PM, said:

How exactly would I figure the proposed position? Using the code with just the player position gives me array out of bounds errors. If I can figure your way out this will be a lot simpler than what I was trying before.


I don't see code for player movement there, so it's hard to say exactly how it would work in your code, but you just capture the movement and hold it until it's approved.


  //X,Y = player's position  
  //Movement commands modify ProposedX,ProposedY rather than X,Y.
  //Proposed is an amount to offset away from current position.
  if (map[x+ProposedX][y+ProposedY] == 2)  
  {
     //Collision Would Occur
  } 
  else
  {
    //Allow movement
    X = X + ProposedX;
    Y = Y + ProposedY;
  }



Of course, you'll have to check if the position is completely out of bounds and prevent that from being evalutated.

This post has been edited by BBeck: 13 June 2012 - 10:33 AM

Was This Post Helpful? 0
  • +
  • -

#8 SYNYST3R1   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 6
  • Joined: 28-August 11

Re: Java - 2d array Tile map collision

Posted 13 June 2012 - 11:22 AM

View PostBBeck, on 13 June 2012 - 10:32 AM, said:

View PostSYNYST3R1, on 12 June 2012 - 06:56 PM, said:

How exactly would I figure the proposed position? Using the code with just the player position gives me array out of bounds errors. If I can figure your way out this will be a lot simpler than what I was trying before.


I don't see code for player movement there, so it's hard to say exactly how it would work in your code, but you just capture the movement and hold it until it's approved.


  //X,Y = player's position  
  //Movement commands modify ProposedX,ProposedY rather than X,Y.
  //Proposed is an amount to offset away from current position.
  if (map[x+ProposedX][y+ProposedY] == 2)  
  {
     //Collision Would Occur
  } 
  else
  {
    //Allow movement
    X = X + ProposedX;
    Y = Y + ProposedY;
  }



Of course, you'll have to check if the position is completely out of bounds and prevent that from being evalutated.


When I add a proposed x it just goes out of bounds again. I have it set to print to console if I collide and it never does. If I put == 0 it constantly collides even when I'm not on the 0 tiles. What I could find online told me to do it like this, but I'm still not getting collision. If I don't divide the 32 then the array goes out of bounds

if (tiles.map[((int)x+32)/32][((int)y+32)/32] == 2)
        {
            System.out.println("Collided");
        }

Was This Post Helpful? 0
  • +
  • -

#9 BBeck   User is offline

  • Here to help.
  • member icon


Reputation: 792
  • View blog
  • Posts: 1,886
  • Joined: 24-April 12

Re: Java - 2d array Tile map collision

Posted 13 June 2012 - 11:46 AM

Quote

When I add a proposed x it just goes out of bounds again. I have it set to print to console if I collide and it never does. If I put == 0 it constantly collides even when I'm not on the 0 tiles. What I could find online told me to do it like this, but I'm still not getting collision. If I don't divide the 32 then the array goes out of bounds


You'll have to prevent it from going out of bounds something like this:

  //X,Y = player's position  
  //Movement commands modify ProposedX,ProposedY rather than X,Y.
  //Proposed is an amount to offset away from current position.
  if (map[x+ProposedX][y+ProposedY] == 2)  
  {
     //Collision Would Occur
  } 
  else
  {
    if (X+ProposedX < XBoundMax && X+ProposedX > XBoundMin
        && Y+ProposedY < YBoundMax && Y+ProposedY > YBoundMin)
    {
      //Allow movement
      X = X + ProposedX;
      Y = Y + ProposedY;
    }
  }



I'm not sure why they are adding or dividing 32.

Anyway, can you post all of the source code for the program? Then I can maybe see what's going on.
Was This Post Helpful? 0
  • +
  • -

#10 SYNYST3R1   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 6
  • Joined: 28-August 11

Re: Java - 2d array Tile map collision

Posted 13 June 2012 - 01:00 PM

[quote name='BBeck' date='13 June 2012 - 11:46 AM' timestamp='1339613163' post='1643923']

Quote

I'm not sure why they are adding or dividing 32.

Anyway, can you post all of the source code for the program? Then I can maybe see what's going on.


This is in my tile class I just edited it to be its own method.

public boolean checkCollision(int x, int y) {
        int xTile= x / tileWidth;
        int yTile = y / tileHeight;
        if (map[xTile][yTile] == 2)
            return true;
            else 
            return false;
    }


Player class

public class Player {
    
    Image player;
    float x = 400;
    float y = 300;
    float speed = 0.3f;
    
    int playerWidth = 52;
    int playerHeight = 76;
    
    Tiles tiles = new Tiles();
    
    
    public void init() throws SlickException {
        player = new Image("assets/player.png");
    }
    
    public void update(GameContainer gc, int delta) {
        Input input = gc.getInput();
          
        if(input.isKeyDown(Input.KEY_A)&& !tiles.checkCollision((int)x-1,(int)y)) {
            x -= speed * delta;
        }
        if(input.isKeyDown(Input.KEY_D)&& !tiles.checkCollision((int)x+playerWidth,(int)y)) {
            x += speed * delta;
        }
        
        if(input.isKeyDown(Input.KEY_W)&& !tiles.checkCollision((int)x,(int)y-1)) {
            y -= speed * delta;
        }
        if(input.isKeyDown(Input.KEY_S)&& !tiles.checkCollision((int)x,(int)y+playerHeight)) {
            y += speed * delta;
        }

    }

    public void render(Graphics g) {
        player.draw(x,y);
    }


I'm not sure all what you want to see, but this is what I have so far. The 32 is the dimensions of the tiles.
Was This Post Helpful? 0
  • +
  • -

#11 stayscrisp   User is offline

  • フカユ
  • member icon

Reputation: 1040
  • View blog
  • Posts: 4,325
  • Joined: 14-February 08

Re: Java - 2d array Tile map collision

Posted 13 June 2012 - 01:13 PM

if (tiles.map[((int)x+32)/32][((int)y+32)/32] == 2)
        {
            System.out.println("Collided");
        }




If you don't understand this code then you shouldn't be using it. I'll attempt to explain but it's difficult without the rest of your code.

The 32 would appear to be tile width and height. This should not be hardcoded, it should be a variable such as tileWidth and tileHeight. You would call this code before you move your character and then if it is a collision then do not move any further.

Let's say that your characters position is x = 75 y = 45

Attached Image

you can work out which tile your character is in by dividing it's current position by the width and height of the tiles. So in this case 75 / 32 = 2 (rounded down) and 45 / 32 = 1 (rounded down). So looking at that image I posted you can see that your current tile is 2 across and 1 down (with a zero index) which is exactly what that code will get out of the array for you tiles.map[2][1]. It will the check if this tile has been set to 2 which is the value for a collidable tile. So you see the reason you will get an out of bounds error is that you do not have that amount of tiles in the array, certainly if your character is at x = 500 y = 500 then you would essentially be saying that your array has at least 250000 elements (your map would be 16000 x 16000 pixels).

The reason the 32 is added is so that you are testing against the right hand side and bottom of the character which you will want when the character is moving right or down. the 32 is also a magic number (very bad) and should actually be a variable such as playerWidth and playerHeight.

I hope that helps some.
Was This Post Helpful? 1
  • +
  • -

#12 BBeck   User is offline

  • Here to help.
  • member icon


Reputation: 792
  • View blog
  • Posts: 1,886
  • Joined: 24-April 12

Re: Java - 2d array Tile map collision

Posted 13 June 2012 - 02:13 PM

View PostSYNYST3R1, on 13 June 2012 - 01:00 PM, said:

This is in my tile class I just edited it to be its own method.

public boolean checkCollision(int x, int y) {
        int xTile= x / tileWidth;
        int yTile = y / tileHeight;
        if (map[xTile][yTile] == 2)
            return true;
            else 
            return false;
    }


Player class

public class Player {
    
    Image player;
    float x = 400;
    float y = 300;
    float speed = 0.3f;
    
    int playerWidth = 52;
    int playerHeight = 76;
    
    Tiles tiles = new Tiles();
    
    
    public void init() throws SlickException {
        player = new Image("assets/player.png");
    }
    
    public void update(GameContainer gc, int delta) {
        Input input = gc.getInput();
          
        if(input.isKeyDown(Input.KEY_A)&& !tiles.checkCollision((int)x-1,(int)y)) {
            x -= speed * delta;
        }
        if(input.isKeyDown(Input.KEY_D)&& !tiles.checkCollision((int)x+playerWidth,(int)y)) {
            x += speed * delta;
        }
        
        if(input.isKeyDown(Input.KEY_W)&& !tiles.checkCollision((int)x,(int)y-1)) {
            y -= speed * delta;
        }
        if(input.isKeyDown(Input.KEY_S)&& !tiles.checkCollision((int)x,(int)y+playerHeight)) {
            y += speed * delta;
        }

    }

    public void render(Graphics g) {
        player.draw(x,y);
    }


I'm not sure all what you want to see, but this is what I have so far. The 32 is the dimensions of the tiles.



Ok. I think I'm starting to get it, especially with StayCrisp's explanation. The x,y is pixel position. You have to divide it by the tile size to get the grid square number.

So, I think I see a problem, if I'm reading the code right:

        if(input.isKeyDown(Input.KEY_A)&& !tiles.checkCollision((int)x-1,(int)y)) {
            x -= speed * delta;
        }



This says to check for collision 1 pixel below current position.

When it goes through this, it's going to calculate the wrong grid square:
public boolean checkCollision(int x, int y) {
        int xTile= x / tileWidth;
        int yTile = y / tileHeight;
        if (map[xTile][yTile] == 2)
            return true;
            else 
            return false;
    }


Since you are kind of using the pixels as a float (real number) you could either do it like this:

        if(input.isKeyDown(Input.KEY_A)&& !tiles.checkCollision((int)x-tileHeight,(int)y)) {
            x -= tileHeight;
        }



or this might give you closer to what you're looking for because it doesn't limit movement to discreet movement between tiles.

        if(input.isKeyDown(Input.KEY_A)&& !tiles.checkCollision((int)x-speed * delta,(int)y)) {
            x -= speed * delta; //Not sure what speed and delta are exactly so don't know about this line.
        }



Also, keep a lookout for rounding errors.

X,Y is the pixel position. FLOOR(X/TileWidth),FLOOR(Y/TileHeight) is the grid square number (tile number). I think the collision is checked against a 2D array of tile values. Anyway, with the Floor function and the division, you could easily point to a different tile than what you intended, if you're not careful. With floor x24,y60 will evaluate to X0,Y1 which should match up nicely with the grid of tiles.

This post has been edited by BBeck: 13 June 2012 - 02:25 PM

Was This Post Helpful? 0
  • +
  • -

#13 SYNYST3R1   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 6
  • Joined: 28-August 11

Re: Java - 2d array Tile map collision

Posted 13 June 2012 - 02:26 PM

View PostBBeck, on 13 June 2012 - 02:13 PM, said:

View PostSYNYST3R1, on 13 June 2012 - 01:00 PM, said:

This is in my tile class I just edited it to be its own method.

public boolean checkCollision(int x, int y) {
        int xTile= x / tileWidth;
        int yTile = y / tileHeight;
        if (map[xTile][yTile] == 2)
            return true;
            else 
            return false;
    }


Player class

public class Player {
    
    Image player;
    float x = 400;
    float y = 300;
    float speed = 0.3f;
    
    int playerWidth = 52;
    int playerHeight = 76;
    
    Tiles tiles = new Tiles();
    
    
    public void init() throws SlickException {
        player = new Image("assets/player.png");
    }
    
    public void update(GameContainer gc, int delta) {
        Input input = gc.getInput();
          
        if(input.isKeyDown(Input.KEY_A)&& !tiles.checkCollision((int)x-1,(int)y)) {
            x -= speed * delta;
        }
        if(input.isKeyDown(Input.KEY_D)&& !tiles.checkCollision((int)x+playerWidth,(int)y)) {
            x += speed * delta;
        }
        
        if(input.isKeyDown(Input.KEY_W)&& !tiles.checkCollision((int)x,(int)y-1)) {
            y -= speed * delta;
        }
        if(input.isKeyDown(Input.KEY_S)&& !tiles.checkCollision((int)x,(int)y+playerHeight)) {
            y += speed * delta;
        }

    }

    public void render(Graphics g) {
        player.draw(x,y);
    }


I'm not sure all what you want to see, but this is what I have so far. The 32 is the dimensions of the tiles.



Ok. I think I'm starting to get it, especially with StayCrisp's explanation. The x,y is pixel position. You have to divide it by the tile size to get the grid square number.

So, I think I see a problem, if I'm reading the code right:

        if(input.isKeyDown(Input.KEY_A)&& !tiles.checkCollision((int)x-1,(int)y)) {
            x -= speed * delta;
        }



This says to check for collision 1 pixel below current position.

When it goes through this, it's going to calculate the wrong grid square:
public boolean checkCollision(int x, int y) {
        int xTile= x / tileWidth;
        int yTile = y / tileHeight;
        if (map[xTile][yTile] == 2)
            return true;
            else 
            return false;
    }


Since you are kind of using the pixels as a float (real number) you could either do it like this:

        if(input.isKeyDown(Input.KEY_A)&& !tiles.checkCollision((int)x-tileHeight,(int)y)) {
            x -= tileHeight;
        }



or this might give you closer to what you're looking for because it doesn't limit movement to discreet movement between tiles.

        if(input.isKeyDown(Input.KEY_A)&& !tiles.checkCollision((int)x-speed * delta,(int)y)) {
            x -= speed * delta; //Not sure what speed and delta are exactly so don't know about this line.
        }



Speed just literally changes the speed I move at. Delta is a variable that changes if the FPS changes, it is a part of the slick 2D library. I will look into what you suggested and see if I can get it to work.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1