Getting More out of Seamless Tiles
Page 3 of 7
<1 | 2 | 3 | 4 | 5 | 6 | 7>
Single-page view
Getting More out of Seamless Tiles

Smooth Transitions between Regions

Using seamless tiles can go a long way towards hiding the underlying grid.

What you do between regions is an important consideration. There are two basic options:

  • Borders between regions coincide with borders between tiles. Thus, each tile can be of only one type of region.
  • Borders between regions are inside tiles. Thus, a single tile may have many different region types.

The main advantages of the first scheme are that it is straightforward to implement and requires fewer tiles (only n tiles for n regions).

The second scheme allows you to blend between regions, and can therefore make the game look more organic. However, for the same number of regions it uses a lot more tiles – for n regions, you will need n4 tiles (if your tiles are square and asymmetric). Also, the implementation is more difficult. It is discussed in more detail in the section below.

IMPLEMENTATION

When using this scheme, you should not map logical cells with tile cells one-to-one. Instead, let the corners of your tiles map to the logical cells. This approach makes it very easy to select tiles that match up properly. Below is pseudo code for the algorithm. The logical grid runs from 0..m, 0..n, and the tile grid from 0..m-1, 0..n-1. Note that the 1 cell border of the logical grid should not be "part of the game" – it is only used for choosing tiles.

for (i = 0; i < m – 1; i++)
  for (j = 0; j < n – 1; j++)
    tile_grid = select_tile(
      logic_grid[i, j], //top left
      logic_grid[i + 1, j], //top right
      logic_grid[i, j + 1], //bottom left
      logic_grid[i + 1, j + 1]) //bottom right

The select_tile function takes four cells from the logic grid – these cells corresponds to the four corners of the tile – and computes the tile to use.

The easiest way to compute the tile is to use a multidimensional array or hash table. (In this case, the function call to select_tile can be replaced by a lookup in the table or array). The trick is then to set up this table to begin with.

By hand

For a small number of tiles, this is a valid approach. But it becomes unwieldy for even moderate tile sizes. Typically, it would look something like this:

tiles[0, 0, 0, 0] = tile_gggg.png
tiles[0, 0, 0, 1] = tile_gggs.png
…

Use a naming convention to load the array

For larger tile sets, this approach is much more manageable. Typically, you will put all the tiles in a folder. The program will then read in all the file names in that folder, and parse in the essential information. It will then put the filename (or loaded image) in the lookup.

In the pseudo-code below, the function parse_tile_info returns an array of integers that corresponds to the four tile corners. For example, the tile of all grass tile_gggg will yield the array [0, 0, 0, 0], and tile_gsgs (half grass and half stone) will yield [0, 2, 0, 2].

tile_file_list = get_tile_list_from_directory(tile_dir)
foreach(tile_file in tile_file_list)
{
  tile_type_corners = parse_tile_info(tile_file) 
  tiles[tile_type_key
    tile_type_corners [0],
    tile_type_corners[1],
    tile_type_corners[2],
    tile_type_corners[3]] = tile_file 
}

This approach requires some discipline in naming files correctly.

Use automation and serialisation

For tile sets with many regions, painting them by hand is not feasible. It is, however, possible to create them from source images (the algorithm is discussed in the next section). When you create tiles in this way, you can fill a lookup table as you create your tiles. This table can then be serialised to be loaded by your game. If your language does not have built-in serialisation support, it is easy to create an XML file, which can be easily be read in by an XML parsing library available for almost any language. You may even consider writing out a file that can be compiled (or interpreted) directly.



Words from the readers
No comments posted for this article yet. Have something to say? Make yourself heard below.
Have your say: