1
\$\begingroup\$

So I am making a tiled game and I need to connect textures correctly based on whats next to it.

With tiles that had connection really close to the edge of the tile I could just use the 4 bit meathod ie:

x 1 x 8 x 2 x 4 x 

But for tiles with more detail I need to have corners too. I have seen people use the 8 bit meathod ie:

1 2 4 128 x 8 64 32 16 

But really I can only see 48 different tile combos.

Is there a way I can separate corners and u d l r. Something like this:

x 1 x 8 x 1 8 x 2 x x x x 4 x 4 x 2 

Or is there a better way all together to do this.

This is what I have tried so far but this only uses 32/48 tiles and doesn't work for special corner cases.

public class RockTile extends Tile { int y; public RockTile(int id) { super(id); y = 7; } public TextureRegion getTexture(Level level, int xLoc, int yLoc){ int u = (level.getTile(xLoc, yLoc + 1) != this) ? 1 : 0; int r = (level.getTile(xLoc + 1, yLoc) != this) ? 2 : 0; int d = (level.getTile(xLoc, yLoc - 1) != this) ? 4 : 0; int l = (level.getTile(xLoc - 1, yLoc) != this) ? 8 : 0; int bit = u + r + d + l; int ur = (level.getTile(xLoc + 1, yLoc + 1) != this) ? 1 : 0; int dr = (level.getTile(xLoc + 1, yLoc - 1) != this) ? 2 : 0; int dl = (level.getTile(xLoc - 1, yLoc - 1) != this) ? 4 : 0; int ul = (level.getTile(xLoc - 1, yLoc + 1) != this) ? 8 : 0; int corner = ul + ur + dl + dr; if (bit == 0) { if (corner != 0) return Game.splitTiles[y + 1][corner]; else return Game.splitTiles[y][bit]; } else { if (corner != 0) if (dl > 0 && l == 0 && d == 0) return Game.splitTiles[y + 2][bit]; else return Game.splitTiles[y][bit]; else return Game.splitTiles[y + 2][bit]; } } } 

If you need anything else let me know.

EDIT: Side question because I've seemed to have stumped you guys. If I decided to use the 8 bit method what would be the best and fastest way to make a lookup table for that.

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

For my system I use a spritesheet with 16 tile variations on it.

Upon creating a tile type I cut up the texture into regions specified in the constructor (which means my tiles can have varying resolutions).

That means you can provide it with an image like this http://www.promagra.de/Downloads/Platformer/Pl5t.png and the transitions will take care of themselves.

The is my simplified constructor for a tile type:

public class TileType { public final TextureRegion[] tileVariations; public TileType(String name, Texture texture, int regionSize){ tileVariations = new TextureRegion[16]; TextureRegion[][] tmp = TextureRegion.split(texture, regionSize, regionSize); tileVariations[0] = tmp[3][0]; tileVariations[1] = tmp[2][0]; tileVariations[2] = tmp[3][1]; tileVariations[3] = tmp[2][1]; tileVariations[4] = tmp[0][0]; tileVariations[5] = tmp[1][0]; tileVariations[6] = tmp[0][1]; tileVariations[7] = tmp[1][1]; tileVariations[8] = tmp[3][3]; tileVariations[9] = tmp[2][3]; tileVariations[10] = tmp[3][2]; tileVariations[11] = tmp[2][2]; tileVariations[12] = tmp[0][3]; tileVariations[13] = tmp[1][3]; tileVariations[14] = tmp[0][2]; tileVariations[15] = tmp[1][2]; } } 

Then every time an individual tile type has its tile type updated, I recalculate which sprite to use for the tile and its neighbours. The sprite to use is stored as an int / byte which is used to access a specific index of the tile variations array of the tile type.

Then you can simply render the correct texture of the tile type based on the display index of an individual tile.

Here is a simplified MapTile class:

public class MapTile { public final int xPos; public final int yPos; private final TileMap tileMap; private TileType tileType; private byte displayTile = 0; public MapTile(int x, int y, TileMap map){ xPos = x; yPos = y; tileMap = map; } public void setTileType(TileType newType){ tileType = newType; // Check the current tile checkNeighbours(); MapTile neighbourTile; // Check the tile above neighbourTile = tileMap.getTile(xPos, yPos + 1); if(neighbourTile != null){ neighbourTile.checkNeighbours(); } // Check the tile below neighbourTile = tileMap.getTile(xPos, yPos - 1); if(neighbourTile != null){ neighbourTile.checkNeighbours(); } // Check the tile to the left neighbourTile = tileMap.getTile(xPos - 1, yPos); if(neighbourTile != null){ neighbourTile.checkNeighbours(); } // Check the tile to the right neighbourTile = tileMap.getTile(xPos + 1, yPos); if(neighbourTile != null){ neighbourTile.checkNeighbours(); } } public void checkNeighbours(){ displayTile = 0; if(this.tileType == null){ return; } // Check the tile above MapTile neighbourTile = tileMap.getTile(xPos, yPos + 1); if(neighbourTile != null){ if(neighbourTile.tileType == tileType ){ displayTile += 1; } } // Check the tile below neighbourTile = tileMap.getTile(xPos, yPos - 1); if(neighbourTile != null){ if(neighbourTile.tileType == tileType ){ displayTile += 4; } } // Check the tile to the left neighbourTile = tileMap.getTile(xPos + 1, yPos); if(neighbourTile != null){ if(neighbourTile.tileType == tileType ){ displayTile += 2; } } // Check the tile to the right neighbourTile = tileMap.getTile(xPos - 1, yPos); if(neighbourTile != null){ if(neighbourTile.tileType == tileType ){ displayTile += 8; } } } public void renderTile(SpriteBatch batch){ if(tileType != null){ batch.draw( tileType.tileVariations[displayTile], xPos * tileMap.tileSize, yPos * tileMap.tileSize, tileMap.tileSize, tileMap.tileSize ); } } } 
\$\endgroup\$
0
\$\begingroup\$

I am also picking tile variations based on a tile's eight neighbors. Encoding the neighborhood is fairly simple, but deciding what pattern each set of bits represents is kind of tricky. I currently just have collections of matching ints for each pattern, and I am checking each pattern type for containment.

I do have the impression that a Binary Trie could be used for fast pattern matching. For example if you changed the encoding order of the neighbors you could arrange for matching configurations to all have the same bit-prefix.

You can read more about what I came up with so far in this blog post.

\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.