First off, by "terrain" I am referring to the background or base layer of graphics for the map display. Terrain might refer to normal terrain types, such as grasslands or forests, but it is not limited to this. In a science-fiction game, for instance, the terrain could be bare metal or even the landscape features of another planet.
The problem of terrain transitioning grows out of the need for a single type of terrain to be able to mesh with itself and still look good when placed next to another terrain. A forest tile should fit together with other forest tiles so that the forest proceeds seamlessly from one map cell to the next. But what happens when the forest tile is placed next to another type of terrain, such as mountains or grassland? Without some form "transitioning" the map looks very blocky and artificial.
Figure 1: Terrain Without Transitions
One solution to the problem is to create specialized transition tiles that "blend" sections of each terrain into a single tile. However, the need for all terrains to transition into any other means that the number of specialized tiles escalates quickly. It may not be obvious at first glance, but the number of transitions required even between just 2 terrain types is quite large. On a square grid, there are 8 possible points of transition: one for each side and one for each corner. Even the simple forest-to-grassland transition would require 256 transitions, and this would have to be done for each terrain transition combination. If you have 9 or 10 terrain types, the amount of graphics this approach would require is unworkable.
This can be refined some by using transitions with a transparent element, allowing for more variety with fewer tiles. The forest transitions would then be able to overlap any terrain. But 256 transition variations for each terrain type still seems pretty excessive.
So how do you trim down the number of required transition graphics to a number that is more manageable? This is how we did it.
The first part of our solution was to assign a "precedence" to the various terrain types. By precedence, I mean that when two different terrain types meet, one of them invariably "overlaps" the other. In the example of forest meeting grassland, if forest has a higher precedence (and it should) then it will always overlap the grassland.
In Artifact, we used the following terrain precedence (listed highest to lowest): jungle, forest, mountain, hill, swamp, deserts, grassland, water (open water or river). Please note that this precedence does not reflect the relative elevations of the terrain but is instead based on which terrains looks best when overlapping other terrains.
Figure 2: Artifact Terrain Precedence
The next step was to reduce the number of terrain transition variations from 256. This number can be cut drastically by separating the "edge" transitions and the "corner" transitions. As it was pointed out above, a single terrain cell has 8 points of transition: one for each side and one for each corner. Thus, there are only 16 possible edge transitions, and 16 possible corner transitions. By using combinations of edge and corner transitions you can create all of the necessary 256 variations with only 32 total tiles. This is a huge reduction in graphics required.
The template we used followed a binary format. For the edges, west was considered "bit 0", north was "bit 1", and east and south were "bit 2" and "bit 3", respectively. Similarly for the corners, the northwest corner was "bit 0", the northeast corner "bit 1", and so on. How we arranged the actual terrain transition graphics is demonstrated in Figure 3. If you think of the covered edges as 1 and the non-covered edges as 0, you can see that the columns proceed in normal binary manner: 0000, 0001, 0010, 0011, 0100, and so on.
Figure 3: Terrain Transition Template
Figure 4 shows how this was applied to create the grassland transitions in Artifact.
Figure 4: Artifact Grassland Transitions
With this method drawing the map is now a 2-step process. For each map cell, the base terrain must be drawn, and then any transitions that overlay it in reverse order of precedence (lowest precedence drawn first). However, the reduction in graphics required more than makes up for the additional work. Also, since the transition graphics are mostly transparent, the actual "work" involved is less than it might seem.
Using the precedence established earlier, and the bit assignments for the edges and corners, calculating which transitions you need in a particular map cell is relatively straightforward. Essentially, for each map cell, you check all adjacency possibilities for terrain types that overlap the terrain of the cell. The transition information for a single terrain type need only use 8-bits of data (4 bits for the edges and 4 bits for the corners) which fits conveniently into a single byte. Thus, the total terrain transition information for Artifact's 9 terrain types requires only 9 bytes per map cell.
You can pre-calculate the transition information and store it with the map, or you can calculate it "on the fly" at runtime. For rendering Artifact's map display, I calculate the transitions for the visible portion of the map only. This reduces the amount of storage required since only a small portion of the map is visible at one time.
A quick example: To calculate the transitions needed for a hill terrain, you need only consider any adjacent jungles, forests, and mountains, since those are the only terrain types that have a higher precedence. Figure 5 demonstrates the overlapping of transitions on the base terrain graphics, with a hill as the center terrain.
Figure 5: Artifact Terrains, Before and After
With a bit of preparation in the graphics and a few tricks during the rendering, you can achieve professional-looking terrain transitions in your game. While drawing the map becomes a bit more complicated, the reduction in graphics required and the flexibility of the system more than make up for that.