Two really famous tile-based games ! |
WHAT DOES "TILE-BASED" EXACTLY MEANS
Tiles are basically small square images that are used to compose a bigger picture just like you would do in a puzzle game.
They usually represent part of the gaming environment (think about "Super Mario" or "Atomic Bomberman") like grass, rocks, platforms, trees etc... and they were also used as a repetetive pattern for backgrounds.
In DickDynamite we used the same principle, using a 20x20 grid to generate our mazes and creating many different "blocks" to create the environment.
To create a tilebased game you should start by defining a "grid" and a tile size: the grid will hold all of the tiles, and the tile size is chosen basing on the dimensions of the grid.
In our example we will be using a 20x20 grid and we will set the tile size to 20 pixels so that the whole game area is 400x400 pixels wide.
Next thing to do is creating a 2 dimensional array that will hold all the cells of our grid:
by doing so we keep an in-memory version of the map that will be very useful to make our sprites detect obstacles and free passages in the map. I find this approach very good as it is fast and needs very few resources.
The array will also be used for drawing the map on screen: for our sample we just use 1 tile, so in the map we can set every cell that contains a tile to 1 and every other cell to 0.
This code generates a 20x20 map using a bi-dimensional array:
function generateMap()
{
map = new Array();
map[0] = new Array(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)
map[1] = new Array(1,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,1)
map[2] = new Array(1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1)
map[3] = new Array(1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1)
map[4] = new Array(1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1)
map[5] = new Array(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1)
map[6] = new Array(1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1)
map[7] = new Array(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1)
map[8] = new Array(1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)
map[9] = new Array(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1)
map[10] = new Array(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1)
map[11] = new Array(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1)
map[12] = new Array(1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)
map[13] = new Array(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1)
map[14] = new Array(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1)
map[15] = new Array(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1)
map[16] = new Array(1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)
map[17] = new Array(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1)
map[18] = new Array(1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1)
map[19] = new Array(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1)
}
Don't get scared by this one. This is just what the map looks like in memory, we have done this manually just for the
purposes of this example, in real life you would use a map editor to help you with the creation of these maps! (more on this in a future article)
What's going on here ?
For each array position (columns) we create a nested array (rows) with 20 elements, giving life to a bidimensional array.
To access this data we need two indexes (ex: map[3][1]) : the first one is the column number (y) and the second one is the row number (x).
If we want to retrieve the item located at column 5, row 8 we will write : var item = map[5][8];
Remember that array indexes start at 0 so the last element is located at map[19][19].
Now that you have defined a map, it's time to write some code and see how to draw this on screen:
function drawIt(theMap)
{
var pos = 0;
for (var y=0; y<20; y++)
{
for (var x=0; x<20; x++)
{
pos = x + (y * 20)
if (theMap[y][x] == 1)
{
_root.attachMovie("myTile", "tile_" + pos, pos)
_root["tile_" + pos]._x = x * 20;
_root["tile_" + pos]._y = y * 20;
}
}
}
}
The drawIt() function takes the array as an argument and cycles through it, when an item is set to 1 it attaches a new
movieclip to the stage and positions it in the right place, based on the x and y variables.
Note that every tile is instantiated with a different name, so that can be referenced via actionscript.
( NOTE: attachMovie() is a method of the MovieClip object that instantiates a new clip taken from the Library.
In order to make this work properly you have to specify the "Linkage" of the symbol in the Flash library. Just select one symbol, right click on it, select Linkage and specify a name )
The variable named pos calculates the absolute index of the tile (from 0 to 399) so that this index can be added to the
end of the name of the new instance.
The expression in the square brackets ( _root["tile_" + pos]._y = y * 20; ) is very similar to writing something like:
tmpClip = eval("_root.tile_" + pos)
tmpClip._x = x * 20;
This evaluates the instance name of the mc attached to the _root, so that we can modify its properties.
Finally we can sum up what we have done so fare in 3 steps:
1) choose a tile size (ex: 20x20 pixels) and a grid size (ex: 20x20 tiles)
2) Generate the maze, using a bi-dimensional array (a grid with columns and rows)
3) Create a simple function that goes through all items in the array and draws tiles accordingly.
Once you have gained some confidence with this approach you can try to expand it, by adding more tiles and creating a simple
"parser" that will attach all of the different tiles that you have created.
Download the zipped example source code. |