With a good amount of C/C++ and basic DirectX knowledge, the reader should be able to go through this tutorial and be able to pick up a few things, I hope. I assume that the reader knows enough DirectX to set up DirectDraw and can load a bitmap from a file to an off-screen surface. I will not be describing how to load bitmaps in this article. Throughout the article, I will be using Windows/DirectX terminology, but for those of you programming for DOS or some other platform, don't worry; all the methods presented are somewhat portable : )
Note: My code may not be the most bug-free in the world, and my techniques may not be the most efficient, but I'm trying my best. Enjoy!
[size="5"]What the Heck is a Tile?
A tile is a small bitmap that is bit-block-transferred, or "blitted" to a surface along with other tiles of similar or different appearances to form a representation of your game world. "Tiling" saves lots of memory by creating virtual bitmaps, as opposed to using a single bitmap for your game. Nowadays, the common tile size is 32*32 or 16*16 pixels, with maps ranging from a few tiles to a few hundred tiles.
During game initialization or setup, maps are loaded from ASCII text files in a format quite like this, where "1" stands for one particular tile, "2" stands for another, and so on.
Maps can also be declared within the code as char arrays, but it is not really preferred. In the tutorial, I'll be using this format even though I strongly suggest using file i/o to load maps from separate files.
Many programmers like to represent their tiled worlds with a tile class or struct, which may include flags for various "walkable" properties (solid vs. non-solid for example), extra items to be placed on specific tiles, animated tiles, and multiple tile layers, to name a few. But for our uses, putting the tiles on the screen, a tile class would be over-doing it a little.
We'll define our tile world like this, a 12 * 12 tile map in a 2D char array.
char map[12][12] = {
{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2},
{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}};
Next, we have to create a bitmap that will store each tile's graphic. You can either create your own tiles, OR you can steal them from your favorite RPG : ) Set it up something like this.
Note: In the tile drawing function, the RECT's are set up so that this format will work. If you would prefer to set up your tiles in the bitmap differently, set up the RECT's accordingly.
Finally, we can now create a function to turn that little char array filled with 1's and 2's into a graphical, DirectX display. Make sure you have DirectX already set up and running. I will go through each piece of code "NeHe style," since he has inspired me to write a tutorial and because his tutorials are always the easiest to understand.
#define TILE_SIZE 32
#define WORLD_SIZEX 12
#define WORLD_SIZEY 12
Here we defined the tile size as 32*32 pixels, and the world size with 12 tiles high and 12 tiles wide.
void draw_tiles(void)
{
int tile;
int x;
int y;
RECT tile_src;
for (y = 0; y < WORLD_SIZEY; y++)
{
for (x = 0; x < WORLD_SIZEX; x++)
{
tile = map[y][x]; // tile now stores the ID of this particular tile
Note: Our function goes through each tile one by one and blits each tile one by one. It is because of page flipping that it seems as if all of them are being blitted at the same time.
tile_src.left = (tile - 1) * TILE_SIZE;
tile_src.top = 0;
tile_src.right = tile * TILE_SIZE;
tiel_src.bottom = TILE_SIZE;
BltFast(x * TILE_SIZE, y * TILE_SIZE, lpddsoffscreen, &tile_src, NULL);
}
}
}
[size="5"]Conclusion
This is my first article for GameDev.net and I plan to write more on the future. I'll be happy if this article helps anyone who's having trouble with these tiling methods or is new to DirectX. If something's wrong with the article, or you want to say you liked it (or hated it), please [email="lpsoftware@home.com"]email me[/email]. Also, if the article helped to create a game, please tell me.
[size="5"]The next article
The next article will be building on this one and will possibly include scrolling with bigger worlds, clipping the tiles, collision detection, and animated tiles.
This article is (C) 2000 Martin Estevao. This article may not be re-printed without the author's consent.