Tegel documentation

    :     :     :     :     :     :     :     :     :     :
  --------:  ---------:  ---------:  ---------:  ----     :
..|      |*..|       |*..|       |*..|       |*..|  |*....:.
  |      |*  |       |*  |       |*  |       |*  |  |*    :
  ---  ---*  |  |-----*  |  |-----*  |  |-----*  |  |*    :
....|  |*.:..|  |--****..|  |-----*..|  |--****..|  |*....:.
    |  |* :  |    |*  :  |  |--  |*  |    |*  :  |  |*    :
    |  |* :  |  |--*  :  |  |*|  |*  |  |--*  :  |  |*    :
....|  |*.:..|  |-----:..|  ---  |*..|  |-----:..|  -----.:.
    |  |* :  |       |*  |       |*  |       |*  |      |*:
    |  |* :  |       |*  |       |*  |       |*  |      |*:
....----*.:..---------*..---------*..---------*..--------*:.
    :**** :   *********   *********   *********   ********:
    :     :     :     :     :     :     :     :     :     :

Tegel Edit, a tilemap editor, v0.82

Copyright (c) 2002-2007

Martijn "Amarillion" van Iersel.

The latest version of tegel is available at http://tegel.sourceforge.net

I hope you like this program. Please send questions, comments, flames and feature requests to amarillion@yahoo.com

Table of Contents

1. Introduction

Tegel is a package for writing games which use tilemaps. The package contains a C library and an advanced editor. Tegel supports various special tilemap tricks such as:

If you're impatient you can find a quickstart tutorial in chapter 5.1

2. Installation

Tegel depends on a couple of other libraries that need to be installed before you can compile it. These are:

note: MASkinG and Alfont are only required for the editor. In principle it is possible to compile the playback library and examples without these.

Once you haveproperly set up these prerequisites the process of compiling tegel should be simple enough

windows:

fix mingw32
make
make install

linux:

./fix.sh linux
make
sudo make install

If you can't or don't want to install MASkinG, you can still compile the library and the examples with make examples or make lib

3. Managing Tilelists

3.1 How to create a tilelist

The first thing you need to do before you can start making maps is create a tilelist. A tilelist is a set of tiles that are loaded as a unit. They are separate from the maps using them. This allows you to save memory when you have many maps using the same tilelist.

A tilelist consists of a datafile containing all the tiles, and a text file which contains the properties of the tilelist. This textfile is grabbed as a binary object in the datafile.

There are four basic types of tilelist:

note: below the new tilelist format version 2 is described. A description of older formats is archived at the end of this help file.

the textfile with the tile properties starts with a header like this:

TILELIST
version=2
tilew=32
tileh=32
bpp=8
flags=2
animsteps=1

The first line "TILELIST" is an identifier that confirms that this is a tilelist file. tilew and tileh are the width and height of the tiles. bpp is the color depth of the tiles. flags is the type of tilelist (1 for bitmap objects, 2 for rle sprites, etc.) animsteps is the number of frames in an animated tileset. If the tileset is not animated, set this to 1.

What follows then depends on the type of tileset. For types 3 & 4, first one object name is specified, this name refers to a bitmap object in the datafile with a width that is a multiple of the specified tile width and a height that is a multiple of the specified tile height.

For types 1 & 2, a list follows with on each line a number and then a list of 1 to animsteps object names. These values can be separated by spaces, tabs, dots, colons, semicolons or any combination thereof. The number may be in decimal, octal or hexadecimal format.

For example:

0xFF, TILE1FRAME1, TILE1FRAME2, TILE1FRAME3

As you can see this tile has a flag value of 255 (hexadecimal: 0xFF) and consists of three frames. If there are more animsteps than the number of objects specified, the specified frames are looped to fill the specified number of animsteps. For example, if in this case the number of animsteps is 6, the actual animation would be:

TILE1FRAME1, TILE1FRAME2, TILE1FRAME3, TILE1FRAME1, TILE1FRAME2, TILE1FRAME3

The specified objects have to be a bitmap (for type 1) or an RLE sprite (for type 2) with widths and heights equal to the specified widths and heights.

For type 3, a similar list follows, but instead of object names you get a list of numbers. Each number is an index that specifies a certain cell of the grid on the bitmap (e.g. 0 specifies upper left cell). Each index should be on a separate line. First all the indices for frame 1, then the indices for frame 2, etc.

The list of object name should end with an exclamation mark (!) alone on a line. This marks the end of the list.

The tilelist file has to be loaded as a separate datafile object in the same datafile as the tiles, with a type value of "TEGT".

Once you've collected your tiles in a datafile and you've created a tilelist property file, you can start up the Tegel editor and start creating tile maps.

4. Using the Editor

4.1 Overview

When you start the editor, you see 4 boxes on the screen and a menu and a toolbar at the top.

When you start the first time, the first step is to load tiles with file->load tiles, then you can create a new map with file->new.

The large box at the top left is the map box. It is used to display and edit maps. Click in the mapbox to make changes. You edit only one layer at the time. The layer that you are edittin is called the "active layer".

The bottom left box is the layer box. It shows which is the active layer, and which layers are currently visible. The active layer is marked with a "*". Click on the layer number with the left mouse button to toggle it on or off. Click with the right mouse button to make it the active layer.

The top right is the tiles box. It shows the currenty loaded tilelist, and you can use it to select a tile. The bottom right is the minimap box. It can be used to give you an overview of the map you are editting, and it can be used to quickly scroll around.

The menu gives you access to various tools.

To make your life easier, you can use a clipboard to copy and paste segments of the map from one place to another. There are two ways to do this. The simplest way is to select an area, copy, place the cursor somewhere on the map and paste. This way the area you selected first gets copied over. The second way to do is to select an area, copy, select another area, and paste. The second area you selected will be filled with as many instances of the original selection as necessary to fill it up.

Currently, the only way to switch between fullscreen and windowed modes is by editing the file allegro.cfg that is in the same directory as the tegel executable. By editing allegro.cfg you can also change the screen resolution / window size of Tegel.

4.2 Menu options

4.3 keyboard shortcuts

5. Writing games with Tegel

5.1 Tutorial

If you have managed to properly install the tegel package, you are probably eager to make a game with it. Here is what you have to do.

Step 1. draw a set of tiles.

Of course you can use one of the sample tilesets that come with tegel and skip ahead a few steps, but assuming that you want to make a tilemap based game, you will really need to draw a couple of your own. You can use your favourite paint program such as the gimp or even MS Paint. You may draw each tile on a separate bitmap or all of them on the same. For organizational reasons it is probably wise to keep the number of bitmap files limited.

Step 2. grab the tiles using the allegro grabber program

Grab the tiles, make sure they all have the same dimensions and color depth. You may grab them as RLE_SPRITE or BITMAP objects, as long as all the tiles in the same set are of the same type.

Step 3. Generate a tilelist information file

See chapter 3.1 on details of how to do that. For the purpose of this tutorial, say you have generated four different tiles and you are not going to use animated tilesets or any other special functions. Then you need a tilelist file that looks something like this:

TILELIST
version=2
tilew=32
tileh=32
bpp=8
flags=2
animsteps=1
0, TILE000
0, TILE001
0, TILE002
0, TILE003
!

use flags=1 if you're using BITMAP objects, use flags=2 if you're using RLE_SPRITE objects. Assuming of course that TILE000 - TILE003 are the names of the grabbed tile objects. The ! in the end is important too - it denotes the end of the list of object names.

The tilelist file has to be loaded as a separate datafile object in the same datafile as the tiles, with a type value of "TEGT".

step 4. create a tilemap using this tilelist

Start the edit program (in tegel/edit/), and use File->Load Tilelist to open the datafile containing the tilelist you just created. Then select File->New Map and start editing. When you're done, use File->Save Map to save.

step 5. load the tilelist and map in your game

you need to include the tegel.h header:

#include <tegel.h>

First you need to install the library. This has to be done after you set up allegro, like this:

allegro_init();
teg_install();

then you can load the datafile and tilemap from disk

DATAFILE *data;
TEG_TILEMAP *map;
data = teg_load_datafile ("tileset.dat");
map = teg_loadmap (
      "level1.map",
      (TEG_TILELIST*)(find_datafile_object (data, "TILESET")->dat)
    )

We need to pass a pointer to TEGTILELIST as the second parameter to tegloadmap. This tilelist object is contained in the datafile loaded in the previous line. Here we use finddatafileobject to obtain a pointer to the tilelist object from the datafile, but we could also have used e.g. data[TILESET].dat if you prefer that construction.

Step 6. draw the tilemap

you can draw the tilemap with the following function call:

teg_draw (screen, map, 0, 0, 0);

alternatively, if you want to make use of the multi-layer functionality you can draw more than one layer like this:

for (i = 0; i != map->layernum; ++i)
{
    teg_draw (screen, map, i, 0, 0);
}

Another common situation is that you want to draw objects between layers, in that case you may want to do it like this:

teg_draw (screen, map, 0, 0, 0); // draw background layer
draw_objects();
teg_draw (screen, map, 1, 0, 0); // draw foreground layer

step 7. clean up

After you are done you'll have to call a few functions to clean up memory:

teg_unload_datafile (data);
teg_destroymap (map);
teg_uninstall ();
allegro_exit ();

As the bitmaps and tilelist information are not copied from the datafile object, you have to keep it around until you are completely done with that tileset. teg_uninstall has to be called before you exit allegro. You may destroy the map using a particular tileset before or after you destroy that tileset.

step 8. look at the examples to learn about the special functionality of tegel

Look at the examples to learn about mode 7 tilemaps, rotated or animated tilemaps. You can also take a look at the API section below to see exactly what each function does.

5.2 API function list

tegel.h functions

The TEG_TILEFLAG_* constants are used for the four different tilelist types

#define TEG_TILEFLAG_BMP 1
#define TEG_TILEFLAG_RLE 2
#define TEG_TILEFLAG_LARGE 3
#define TEG_TILEFLAG_LARGEI 0

These DAT_ID's can be used to identify tegel tilelist or tilemap objects in a datafile.

#define DAT_TEG_TILELIST DAT_ID('T','E','G','T')
#define DAT_TEG_MAP DAT_ID('T','E','G','M')

teg_error contains a friendly description of the last error that occurred.

extern char teg_error[256];

the TEG_TILE struct holds information about a single tile. flags can hold user defined information. The actual bitmap information for this tile is, depending of the tilelist type, held in either rle or bmp, or in a separate bitmap altogether in which case index refers to that. You should rarely need to access the bitmap data directly.

typedef struct TEG_TILE
{
    RLE_SPRITE* rle;
    BITMAP *bmp;
    int index;
    int flags;
} TEG_TILE;

TEG_TILELIST holds a set of tiles. If the tileset is animated, animsteps is determines the number of frames in a cycle (each tile in the set has to have the same number of frames). All tiles need to be the same size, tilew x tileh pixels. Also, they need to be the same number of bits per pixel, as in the bpp parameter. Tilenum holds the number of tiles in this set. pal may refer to palette information for this tilelist, although it may also be NULL. rawdata and rawsize are for internal use.

typedef struct TEG_TILELIST
{
    int flags;
    int tilew, tileh, tilenum;
    int bpp;
    int animsteps;
    TEG_TILE* tiles;
    BITMAP* largebmp;
    RGB *pal;
    char *rawdata;
    int rawsize;
} TEG_TILELIST;

TEG_MAP holds the information about one, multi-layered map. dl, w, and h specify the dimensions of the map (dl stands for delta-layers, or the number of layers in this map). Tilelist is a pointer to the tilelist data for this map.

typedef struct TEG_MAP
{
    int *data;
    int dl, w, h;
    TEG_TILELIST *tilelist;
} TEG_MAP;

teg_createmap and teg_destroymap are a constructor resp. destructor for the map struct. teg_createmap creates a map of the specified size and allocates memory to hold a map of that size. The tilelist parameter may be NULL, in which case it has to be set manually later.

TEG_MAP *teg_createmap (int dl, int w, int h, TEG_TILELIST *tilelist);
void teg_destroymap (TEG_MAP* map);

teg_loadmap loads a map from the specified file and links it with the specified tilelist (which may be null, in which case it has to be set manually later). A map loaded with teg_loadmap should be cleaned up with teg_destroymap to make sure all memory is reclaimed.

TEG_MAP *teg_loadmap (const char *filename, TEG_TILELIST *tilelist);

teg_mapget and teg_mapput can be used to set or get the index of a tile at the specified coordinate.

int teg_mapget (const TEG_MAP* map, int l, int x, int y);
void teg_mapput (TEG_MAP* map, int l, int x, int y, int val);

teg_loadtiles can be used to read tilelist information directly from a text file. However, it is preferable to store tilelists as datafile objects.

TEG_TILELIST *teg_loadtiles (const char *filename, const DATAFILE *data);

A tilelist loaded with teg_loadtiles can be destroyed again with teg_destroytiles. If you use datafiles to store tilelists you'll never need to call this function as the tilelist is cleaned up when you unload the datafile.

void teg_destroytiles (TEG_TILELIST* tiles);

the tegdraw.... functions are used to render a tilemap to the screen (in the normal, non-rotated way). Tegdraw is the simplest version, which fills the complete destination bitmap and can't be used for animated tilesets. xview and yview are offsets that can be used to scroll the map. Tegdrawframe can be used to draw consecutive frames of an animation and when called with a different frame parameter at a steady pace, will result in the fluid animation of the tilemap. teg_draw_rle, teg_draw_bmp, teg_draw_largei and teg_draw_large needn't be called directly, they are tilelist format dependant versions of teg_draw_frame. teg_draw_frame does nothing more than select the proper function to call. If you're worried about the tiny overhead that this creates and you are positive that you'll always use the same tilelist format you may call these directly. The teg_partdraw.... functions only draw to a part of the destination bitmap and may be used to render only part of the tilemap, e.g. in a dirty-rectangle type system.

void teg_draw (BITMAP *bmp, const TEG_MAP* map, int layer, int xview, int yview);
void teg_draw_frame (BITMAP *bmp, const TEG_MAP* map, int layer, int xview, int yview, int frame);
void teg_draw_rle (BITMAP *bmp, const TEG_MAP* map, int layer, int xview, int yview, int frame);
void teg_draw_bmp (BITMAP *bmp, const TEG_MAP* map, int layer, int xview, int yview, int frame);
void teg_draw_large (BITMAP *bmp, const TEG_MAP* map, int layer, int xview, int yview, int frame);
void teg_draw_largei (BITMAP *bmp, const TEG_MAP* map, int layer, int xview, int yview, int frame);
void teg_partdraw (BITMAP *bmp, const TEG_MAP* map,
    int layer, int x, int y, int w, int h, int xview, int yview);
void teg_partdraw_rle (BITMAP *bmp, const TEG_MAP* map,
    int layer, int x, int y, int w, int h, int xview, int yview);
void teg_partdraw_bmp (BITMAP *bmp, const TEG_MAP* map,
    int layer, int x, int y, int w, int h, int xview, int yview);
void teg_partdraw_large (BITMAP *bmp, const TEG_MAP* map,
    int layer, int x, int y, int w, int h, int xview, int yview);
void teg_partdraw_largei (BITMAP *bmp, const TEG_MAP* map,
    int layer, int x, int y, int w, int h, int xview, int yview);

teg_pixelw and teg_pixelh give the dimensions of a particular map not in number of tiles but in number of pixels.

int teg_pixelw(const TEG_MAP *map);
int teg_pixelh(const TEG_MAP *map);

Tegel records links that exist between various resources. For example, a tilelist links to a set of tiles that go with it, and a map links to the tilelist that is supposed to go with it. In the same way an animation may link to the frames that make up the animation, or a set of 8 bit graphics may link to the palette that has to be used to draw them, or a level data file may link to the proper background music for that level. To accomodate these links tegel comes with a specialized datafile loading system. teg_load_datafile and teg_unload_datafile are wrappers around the allegro datafile functions that handle and resolve links between objects. It never hurts to use teg_load_datafile instead of load_datafile, as the overhead is minimal. However, it does give you the additional advantage of storing the links between datafile objects.

DATAFILE *teg_load_datafile (const char *datafile);
void teg_unload_datafile (DATAFILE *data);

teg_install must be called before you use any other teg_ function, but after allegro is installed. teguninstall must be called after any other teg function call.

int teg_install();
void teg_uninstall();

save a map

void teg_savemap (TEG_MAP* map, char *filename);

copy a part of a map to an existing other map.

void teg_mapcopy (TEG_MAP *srcmap, TEG_MAP* destmap,
    int srcl, int srcx, int srcy,
    int destl, int destx, int desty,
    int dl, int w, int h);

map copy constructor. New memory is allocated

TEG_MAP *teg_create_copy (TEG_MAP *src);

fill an area with the same tile index

void teg_maprect (TEG_MAP *destmap,
    int destl, int destx, int desty,
    int dl, int w, int h, int value);

resize a map. As much as possible is kept of the original.

void teg_resizemap (TEG_MAP **map, int newdl, int neww, int newh);

draw a tile, specified by its tile index

void teg_drawtile (BITMAP *dest, TEG_TILELIST *tiles, int index, int x, int y);

some usefull macros

tegmode7.h functions

typedef struct TEG_MODE_7_PARAMS
{
    fixed space_z;
    int horizon;
    fixed scale_x, scale_y;
    fixed obj_scale_x, obj_scale_y;
} TEG_MODE_7_PARAMS;

void teg_draw_object (BITMAP *bmp, BITMAP *obj,
    fixed object_x, fixed object_y, fixed angle,
    fixed cx, fixed cy, TEG_MODE_7_PARAMS params);

void teg_mode_7_sprite (BITMAP *bmp, BITMAP *tile,
    fixed angle, fixed cx, fixed cy, TEG_MODE_7_PARAMS params);

void teg_mode_7_map (BITMAP *bmp, TEG_MAP *map, fixed angle,
    fixed cx, fixed cy, TEG_MODE_7_PARAMS params);

5.3 example programs

The tegel package comes with a set of examples to help you get started quickly.

exanim

shows how to display an animated tilemap, and how to do scrolling

exload

shows three different ways to store tilemap and tilelist data on disk: in separate files, in datafiles or in the same datafile.

exrot

rotated tilemap example

extiles

displays information about a tilelist

exmode7

mode7 tilemap example

6. Depracated Info

(This information is here only for myself, you can safely skip this stuff)

Here is a description of the version 1 tilelist file format. This file format is still supported at the moment but support for this format may be removed in the future without warning, so you shouldn't use it.

The first thing you need to do before you can start making maps is create a tilelist.

A tilelist is a set of tiles that are loaded as a unit. They are separate from the maps using them. This allows you to save memory when you have many maps using the same tilelist.

A tilelist consists a datafile containing all the tiles, and a text file which contains the properties of the tilelist. This textfile is grabbed as a binary object in the datafile.

There are four basic types of tilelist:

the textfile with the tile properties starts with a header like this:

TILELIST
version=1
tilew=32
tileh=32
bpp=8
flags=2
animsteps=1
tilenum=101

the first line "TILELIST" is an identifier that confirms that this is a tilelist file. tilew and tileh are the width and height of the tiles. bpp is the color depth of the tiles. flags is the type of tilelist (1 for bitmap objects, 2 for rle sprites, etc.) animsteps is the number of frames in an animated tileset. If the tileset is not animated, set this to 1. tilenum is the total number of tiles.

Then follow a list of the datafile object names, each on a separate line, specifying the tiles used. depending on the type of tilelist:

type 1: tilenum * animsteps object names, first all the tiles for frame 1, then the tiles for frame 2. The specified objects should all be bitmaps with the specified width and height type 2: the same, tilenum * animsteps names. The specified objects should be rle sprites with the specified width and height. type 3: only one object name, of a bitmap object with a width that is a multiple of the specified tile width and a height that is a multiple of the specified tile height. type 4: one object name, as in type 3, followed by tilenum * animsteps numbers. Each number is an index that specifies a certain cell of the grid on the bitmap (e.g. 0 specifies upper left cell). Each index should be on a separate line. First all the indices for frame 1, then the indices for frame 2, etc.