I guess many of gamedev programmers were thinking about algorithms for map tiling. Just imagining all possible tile combinations can keep your brain boiling! I did several attempts to get some rather simple method which can handle various tile layouts and finally caught something that I like. Here is my version - it is simple to implement and can be expanded for even more complex situations.
Just how many mixed textures we need for all possible layouts with only 2 tiles? And adding new ones increases that number to the degree which I am afraid to imagine. So let's forget for a while about that fear and dive into those combinations to figure out any patterns which will help us to decrease mixing complexity.
Let's start with mixing two different tiles together. Pic.1 - the simpliest tile layout "as it is", and the thing we see at the pic.2 - what we want it to be in our game.
Some more complex layout is presented at pics 3-4. There are dozens of different combinations with those two tile type, so we need something to simplify that.
After drawing some sketches with different combinations I finally figured out that if we divide tile in four parts each of them is affected only by 3 adjacent tiles! Let's look on 5 different mixing patterns:
The one in yellow border is the tile part which is affected by H-V-C adjacent tiles. H - Horizontally adjacent, V - Vertically adjacent, C - the one in the Corner. Using those denotements that pattern appears to be similar for other 3 parts which means that we have to think something out only for the one part and expand that method for the others.
With 3 adjacent tiles there are just 8 different combinations. But why I represented only 5 patterns? Let's compare them:
HCV (all the adjacent tiles are the same as main one): pattern 5 (full main tile)
H-V (corner tile is different): pattern 4
--V or -CV: pattern 3 (got similar one! you can draw both of them by yourself and see that they will give out the same pattern)
H-- or HC-: pattern 2
--- or -C-: pattern 1
At start dozens of combinations shrinked to just 8 ones, and even more - we got only 5 different patterns for every layout we can imagine. Still, the fifth one is pretty trivial - we just need to draw our tile part "as it is". So, for each tile part we need 4 different mixing masks for patterns 1-4. Taking into account 4 tile parts we can get a 4x4 mask and use it to mix every combination we want.
What a neat one! You sure can think out something even more beautiful, I'm using it just to show how the whole thing works. First picture is the mask for the part we traced earlier, and the second one is the combination of masks for all 4 parts:
- top-left part
- top-right part
- bottom-right part
- bottom-left part
Mask represents alpha-channel for drawing the tile part. At white regions we draw our tile part, and at black one it is fully transparent.
So, we have the mask which shows what parts of the tile-2 is drawn. All we need is to start with drawing tile-1 and then draw tile-2 using that mask over the first one.
Here is the screenshot of some tiled layout rendered using described method (and shown mask). Instead of plain-colored tiles we sure can use any textures, and working a bit more on the mix-mask can do some beautiful things.
Okay, we got something to mix up two different tiles. What about adding some more there? Let's look back for a while at what we've done before. Our algorithm:
- draw tile-1
- draw tile-2 with mask
Wanna know what will happen if we switch orders starting with tile-2 and adding masked tile-1 over? Look at the next screenshot:
Pretty different image, isn't it. So, the order is important. We draw first tiled layer and add over the second one. Any ideas about the third tile? Sure! Let's just add a new layer over the existing image. But there are some issues we need to take into account.
At first, we have to decide which tile is placed first, which one is second and so on. Let's imagine some green field with burned-out spots of yellow grass and a river over them. So, green field should be drawn first. Now we mix in some yellow grass and keep in mind that there could be river somewhere. While deciding which mask pattern to use, we should consider that the river is the same tile as the grass, so we can later add some water all over the place. And while we are calculating mask for the river both green and yellow grass must be considered as different tiles.
Here is some technical explanation. Let's say green grass is tile-1 (first in the stack), yellow one is tile-2 and the river is tile-3. Our algorithm:
- draw tile-1
- generate mask layout for tile-2, where all tiles that are less than 2 are representing black color, and all tiles above (including tile-2) - are white.
- draw masked tile-2
- generate mask for the tile-3, again counting previous tiles as black, and current tile with the next ones (if they are there) as white
- draw masked tile-3
- ... (continue until you're out of tiles)
Doesn't it sound simple? It should! Especially compared to all the complexity of combining each pair of tiles together. Just see visual representation of that method:
Sorry about that rivers crossing each other, it's all for the sake of tiling!
That's the main idea. You can use different masks for different layers. You can even take into account difference in mixing up, for example, tile-3 with tile-1 and tile-2 (though it is a bit more complex). There's some room left to play with that method limited by imagination and perfomance issues. Hope you'll find it useful in your creations or at least get some own ideas based on it!