10

I am working on a tiled map editor, and I need to choose tiles automatically, based on the adjacent tiles. For example, when placing a road tile, next to another road tile, the two need to be oriented so that they form a continuous road. If there are other roads around them, we may need to use corner or intersection tiles.

Can anyone recommend some algorithms for doing this? The game uses an 8-directional square tiled map.

House
  • 73,224
  • 17
  • 184
  • 273
alekop
  • 641
  • 2
  • 7
  • 16
  • Can't you just examine all the surrounding 8 tiles whenever the user puts down a new tile, and the orient the new tile accordingly? Of course you'll need to store some extra info on each tile such as orientation and type. – XiaoChuan Yu May 23 '12 at 22:18
  • I am examining all surrounding tiles, but I didn't know how to handle all the tile combinations. For example, you have seven possible tiles to choose from (horizontal, vertical, four corners, and a cross). I thought of using complicated switch statements, but that felt wrong. – alekop May 23 '12 at 23:02

2 Answers2

18

Maybe this is how it's typically done. You have your list of different tiles that represent a road tiles in all their possible orientations. Left to right, all four corners, top to bottom, whatever. Now you'll index all those tiles with a byte each. 8 bits, one for each direction. This could be in a hashmap or by file name... however you want to do this.

So you have this:

enter image description here

The byte code for the above tile is 00000000. Then your tile that goes from left to right (or right to left) is like this:

enter image description here

The byte code for that tile is 10001000, or 136. As another example, lets look at a three way intersection:

enter image description here

The byte code for that tile is 10101000.

You probably see where I'm going. You set bit positions in the byte representing connections. This is far better than trying to do some big if/else chain that I've seen before. When you're looking to place a tile, examine the tiles around it and create a byte along the way. Set 1's for tiles that have roads (or whatever you're looking to connect) and 0's for tiles that don't. When you're done, you'll have the byte code for the exact tile you need.

Note that when creating the assets you can reuse a lot of them by simply rotating and assigning the correct byte code to it.

EDIT: Updated images to be less crappy. Yes those are better than before.

House
  • 73,224
  • 17
  • 184
  • 273
  • Very nice! Simple and efficient. The only thing that I don't understand is how you're getting those bitmasks. For example how are you getting a bitmask of 17 from the numbers 3 and 7? – alekop May 23 '12 at 22:41
  • Never mind, I see what you're doing. You're setting bits 3 and 7, but you're counting from the left, instead of the right. – alekop May 23 '12 at 22:46
  • Oh wow, how embarrassing. Got my Endianness all mixed up. That was an accident I'll fix that! – House May 23 '12 at 22:48
  • Great, now my comment doesn't make sense! :p Just kidding, thanks for your answer. That's exactly what I was looking for. – alekop May 23 '12 at 22:54
  • still this algorithm needs to be optimized, since most of those tiles are just rotation of each other! with your current approach, you need 256 tiles (or 16 if you don't count corners) to store all that data, while most games don't use more than 4 types of tiles. – Ali1S232 Oct 22 '12 at 01:18
  • @Gajoo Actually all this algorithm is doing is telling you the code you need to access the tile. The way in which you retrieve tiles or their rotations are left up to the developer. Mapping multiple byte codes to a single tile or the tile's rotation is perfectly achievable. – House Oct 22 '12 at 01:28
  • I just meant it's kinda nice to provide explanation for that as well. – Ali1S232 Oct 22 '12 at 01:38
  • 1
    Good explanation. I have a blog post covering the same technique with actual code and tile resolution: http://kitsu.github.io/2016/07/18/roguelike-project-05/ – kitsu.eb Jul 19 '16 at 17:48
3

I would recommend you take a look at this handy page for more information, as it goes into great detail about pretty much every aspect of what you're doing, as well as a few potential optimizations: http://www.angryfishstudios.com/2011/04/adventures-in-bitmasking/

The tldr is that you query each adjacent cell and store the combination in a bitfield/byte, then pass it through a map that converts a number from 0~255 into a value from 0~47, which corresponds to a unique image.

Kyle Baran
  • 397
  • 2
  • 14