Tile coords

Hello, i recently finished creating a tile map, I render it using a 2D array, the problem is the way I am rendering, I never really set an X/Y position of the individual tiles, instead I’m using the tiles render method and a loop for setting the X and Y, but of course this is only the drawing positioning and not the actual coordinates of the tile. So is there anyway I can set an x and y for a tile within a 2D array? The main reason is I’m thinking of implementing path finding and cant think of any other way to do it without knowing the specific x,y of the individual tiles. Thanks for any help!

You could store the location of the tile in the Tile class, and have it set when the tile is created.
There are other methods, but this is the simplest.

The problem with that is, I am using a static Tile named grass, I saw no reason to create multiply instances of a tile, the way Im doing it, I’m not creating a new tile for every index in the array, if I did surely that would use a lot more resources considering each tile would have a buffered image assigned to it?

Ah, I wondered if that’s what you were doing. Well you could have non-static tile instances, but each one refers back to a static BufferedImage, stored in the Tile class, E.g:


public class Tile {
    public static List<BufferedImage> images;

    private BufferedImage image;
    private int x,y;

    public Tile(int x, int y, BufferedImage img) {
        this.x = x;
        this.y = y;
        image = img;
}

and when making a new Tile: [icode]new Tile(5,7,Tile.images.get(0));[/icode]
You could also use a Map or something instead of a List.

hmm, I may change it to be like that, though I’m not sure, I just really like the idea of only have one instance, I just can’t really think of any other way to implement path finding without being able to access specific tile coordinates, because without the coordinates there really isn’t a way for me to access the tiles type etc.

Thanks for the help anyway, I’ll wait and see if anyone else has any ideas, if not ill try your idea :slight_smile:

First of all, let’s assume your tile class looks like this, or something along these lines.



public class Tile
{
    public final String name;
    public final BufferedImage image;
    public final boolean passable;

    public Tile(String name, URL imagePath, boolean passable)
    {
       this.name = name;
       this.image = new BufferedImage(ImageIO.read(imagePath));
       this.passable = passable;
    }
}

I don’t care if we might load the properties from a file or what, as long as it has at least these things in it

In your map rendering thing, you could have a parallel 2d array


Tile[] tileSet = {all my different tile types};
int[][] tiles = {
  {0,0,0,0,0},
  {0,1,1,1,0},
  {0,1,2,1,0},
  {0,1,1,1,0},
  {0,0,0,0,0}
}

Your tile set is just all your different tile types in the map. Tiles is an array where all the numbers match with the index of the tile type in tileSet.


public void render(Graphics g)
{
    ...
    //graphics prep stuff
    ...
    for (int row = 0; row < tiles.length; row++)
    {
        for (int col = 0; col < tiles[0].length; col++)
        {
            BufferedImage image = tileSet[tiles[row][col]].image;
            graphics.draw(image, row*Tile.WIDTH, col*Tile.HEIGHT);
        }
    }
    player.sprite.draw(g);
    batch.end();
}

Now, depending on how complex of pathfinding you need, all you might need to do is check the position in your array. I recommend having an enum of Directions


public static enum Direction
{
    North(0,-1), South(0, 1), East(1, 0), West(-1, 0);
    
    public final int x;
    public final int y;
   
    Direction(int x, int y)
    {
        this.x = x;
        this.y = y;
    }
}

Then check a tile collision like so


public boolean doesCollide(int x, int y, Direction d)
{
    return tileSet[tiles[x + d.x][y + d.y]].passable;
}

Each tile type just needs to have a boolean set on it saying if you can step on it or not. More complex collision detection idea where tiles can only be passable from certain directions can work the same way.




public boolean doesCollide(int x, int y, Direction d)
{
boolean passable;
Tile t = tileSet[tiles[x + d.x][y + d.y]];
switch(d)
{
case (North):
passable = t.passableFromSouth;
break;
case (South):
passable = t.passableFromNorth;
break;
case (East):
passable = t.passableFromEast;
break;
case (West):
passable = t.passableFromSouth;
break;
}
return passable;
}



but requires for values to be set with each tile.


Now if you're doing pixel movement of your character, you can take their pixel position and integer divide it back into the array position and use the same collision detection as above


/**

  • Movement by pixels
    */
    public void move(Direction d)
    {
    if (doesCollide((int)(player.sprite.getX() / Tile.WIDTH) , (int)(player.sprite.getY() / Tile.HEIGHT), d)
    {
    player.sprite.translate(d.x, d.y);
    }
    }


and if you don't want to do it by pixels, and instead just by full tiles

public void move(Direction d)
{
if (doesCollide(player.x , player.y, d)
{
player.x += d.x;
player.y += d.y;
player.sprite.setPosition(player.x * Tile.WIDTH, player.y * Tile.HEIGHT);
}
}



That should be enough to handle simple tile maps and collision.  I remember doing something along the same lines awhile ago with another project of mine.  If you want to check it out, it's an RPG engine written using Java2D http://git.io/LQiAFg

Thanks for the help, I managed to sort out my tile problem and it now works as desired, as for the path finding you suggested, I am actually going to use a* path finding, thanks anyway that was a lot of code and I took note of it :slight_smile: