Tile Based Games

This article is intended as an introduction to tile based games. It does not cover isometric or hexagonal grids, but it does include some clever tricks involving rectangular grids, the main one being how to achieve this;

Image


I found most of this out whilst working on an Advance Wars clone (hence the ripped graphics). My eventual aim is to create a complete step-by-step article (including source files) on the creation of this games. For now though, here are the basics of the map editor.

It is strongly recommend that you download the accompanying example file (.cca) here:

http://cid-b1e7ee094271bbda.skydrive.live.com/self.aspx/Public/TileExample.cca


Why Use Tiles?

There are a few good reasons to use tiles. The types of games which are derived from tabletop board games (war, strategy, puzzle etc) often use a grid as an integral part of their mechanics. It is for example, common to see units in a wargame with movement and attack ranges measured in squares. It is only natural therefore, to use square tiles for the graphics.

The main reason tiles were first used in video games however, was to increase performance by reducing memory consumption - a large image uses more memory than many small images, some of which are the same. Even though this shouldn't really be a problem with todays hardware, MMF can usually scroll tile based maps more quickly than those containing large objects.

What I consider to be the main reason for using tiles now, is the ease with which levels may be created. It is much easier to create a good tile based map editor and use that than it would be to create many levels in the Frame Editor. The other bonus is that you can release the level editor along with your game, allowing the player to create their own levels, possibly extending gameplay. By storing the level in an external array file, it becomes possible for players to share their creations with each other aswell.



The Basics

Before I go onto anything else, here are a few simple formulae which may be of use when making a tile based game.

Convert Pixel to Grid Coordinates

X_grid = X_pixel / Cell_width
Y_grid = Y_pixel / Cell_height


Snap Pixel Coordinates to Grid

X_pixel = X_pixel / Cell_width * Cell_width
Y_pixel = Y_pixel / Cell_height * Cell_height


Convert Grid to Pixel Coordinates

X_pixel = X_grid * Cell_width
Y_pixel = Y_grid * Cell_height


Distance from A to B (euclidean)

Dist. = SQRT((Xa - Xb)*(Xa - Xb) + (Ya - Yb)*(Ya - Yb))


Distance from A to B (manhattan - allowing 4 directions of movement between cells)

Dist. = Abs(Xa - Xb) + Abs(Ya - Yb)


Distance from A to B (chebyshev - allowing 8 directions of movement between cells, including diagonals)

Dist. = Max(Abs(Xa - Xb), Abs(Ya - Yb))



Arrays

Arrays represent the perfect data storage solution for tile based games. An array is basically an invisible grid of data, meaning that grid and array coordinates are completely interchangeable, and pixel coordinates are easily calcuated for both. By fastlooping through the array it is even possible to load an entire level almost instantaneously. Any non-animated tiles can be added/pasted to the backdrop at the start of the frame, with any other information being read directly from the array when needed. This avoids the slowdown which would likely be a result of having many active objects on screen.

To be honest, there are already gazillions of tutorials and example files on using arrays, both here and at the clickteam forum. I'm not going to cover it here, but if you want more information, that's where to look. Needless to say, it's really not very difficult at all.



Automatic Tile Selection

The main problem with tile based games is the need for a lot of graphics. Creating full tilesets can be a long and tedious task, and then placing the tiles in the map editor can be almost as much trouble. However, with a little ingenuity and planning it is possible to greatly reduce the amount of work needed, by automating parts of the process.

Basic Example

Image

Just for a simple example, let's take a look at the mountains in Advance Wars. To make the maps more visually appealling, the designers have decided to use two different types of mountain - a small one that fits completely within the 16x16 grid square, and a taller one which overlaps the square above. When using the map editor, it would be quite tedious to have to select which type of mountain to create. Instead, the player has only to select mountain and the correct tile is placed automatically, according to a few simple rules;

Image

Image 1
Use if the square directly above the mountain contains something other than grass or another mountain.

Image 2
Use when the square directly above the mountain contains either grass or another mountain.

Image 3
Use on grass and mountain squares which are directly above a mountain. The pink part is transparent.



Linear Tiling

This second technique is for any objects of a generally linear nature, which can occupy several tiles - eg. roads, walls, etc. Again taking Advance Wars as our example, roads may comprise up to 16 different types of tile (you'll just have to take my word for that though). Manually choosing the exact road tile to place each time would be really annoying.

As with the mountains, the correct choice of road tile is determined by the other tiles around it, and is quite easily found. In this case, it is the four directly adjacent tiles which are of importance. We'll look at each road tile in turn, and repeat the following procedure:

1. Is the tile directly above also a road tile? If so, add 1 to our tile's animation direction.
2. Is the tile directly to the right also a road tile? If so, add 2 to our tile's animation direction.
3. Is the tile directly beneath also a road tile? If so, add 4 to our tile's animation direction (note that we are doubling the amount to add each time, not just adding 1)
4. Is the tile directly to the left also a road tile? If so, add 8 to our tile's animation direction.

Now for this to work, it is essential that the tile directions match the picture below. The numbers correspond to the animation direction value. All of this should be fastlooped, making it virtually instantaneous.

Image

Image



Fringe Tiling

The final technique is for creating smooth boundaries between areas of different types of tile. It works in much the same way, but is a little more complicated.

Taking Advance Wars as our example yet again, the sea may comprise up to 256 different types of tile (you're just gonna have to take my word for it though). Not only would it be a major headache trying to manually choose the correct tile to use out of all those, but it would be pretty tiring even creating that many tiles.

The solution? Well, we use two tiles for each grid cell. Each tile only needs 16 variations, and by overlapping them we can create the required 256 combinations. That means we now only need to make 1/8th as many tiles - cunning eh?

Let's start with the background tile. We'll look at each sea tile in turn, and repeat the following procedure:

1. Is the tile directly up and left a land tile? If so add 1 to our tile's animation direction.
2. Is the tile directly up and right a land tile? If so add 2 to our tile's animation direction.
3. Is the tile directly down and right a land tile? If so add 4 to our tile's animation direction.
4. Is the tile directly down and left a land tile? If so add 8 to our tile's animation direction.

Again, the tile directions must match the picture below.

Image

Next, we'll create another tile overlapping each of our original sea tiles. We'll again look at each tile in turn, and consider the following:

1. Is the tile directly to the left a land tile? If so, add 1 to our tile's animation direction.
2. Is the tile directly above a land tile? If so, add 2 to our tile's animation direction.
3. Is the tile directly to the right a land tile? If so, add 4 to our tile's animation direction.
4. Is the tile directly beneath a land tile? If so, add 8 to our tile's animation direction.

Again, the tile directions must match the picture below. Note that the part shown in pink should be transparent, revealing part of the other tile beneath. Take a look at the example file (link at top of page) to see how this method actually works in practice.

Image

If you wanted to update the tiles in realtime, you could quite easily do so. This would require only that you recheck the 8 squares adjoining the current square each time it is changed. It should be possible to do this using fastloops with minimal slowdown.