: : : : : : : : : :
--------: ---------: ---------: ---------: ---- :
..| |*..| |*..| |*..| |*..| |*....:.
| |* | |* | |* | |* | |* :
--- ---* | |-----* | |-----* | |-----* | |* :
....| |*.:..| |--****..| |-----*..| |--****..| |*....:.
| |* : | |* : | |-- |* | |* : | |* :
| |* : | |--* : | |*| |* | |--* : | |* :
....| |*.:..| |-----:..| --- |*..| |-----:..| -----.:.
| |* : | |* | |* | |* | |*:
| |* : | |* | |* | |* | |*:
....----*.:..---------*..---------*..---------*..--------*:.
:**** : ********* ********* ********* ********:
: : : : : : : : : :
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
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
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
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:
type 1. each tile is a separate bitmap object
type 2. each tile is a RLE sprite object
type 3. all the tiles are on a single large bitmap. The bitmap is divided in tiles using a grid the tile in the upper left corner is tile 0, and right next to it is tile 1, etc.
type 4. same as 3, but rather than using left to right, up to down ordering, the order of tiles can be specified using indices. This can be useful for making animated tilesets.
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.
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.
File->New Create a new map. Only available when you have loaded a tilelist. This opens up a dialog that allows you to specify the width, height and number of layers in the map.
File->Load Map Load a map. Only available when you have loaded a tilelist. A dialog pops up that allows you to select a map file.
File->Save Map Save the map that you created.
File->Import Currently not implemented
File->Load Tiles This allows you to load tiles. You have to specify the datafile containing the tile bitmaps and the textfile with the tilelist properties.
File->Quit end the program
at the end of the file menu, the 4 most recently used map files are shown. You can select these to quickly load one of the maps that you have been working on recently.
Edit->Copy Copy the current selection to the clipboard
Edit->Paste Paste the contents of the clipboard to the map
Edit->Resize Select this to change the dimensions of the map, or to add extra layers. Warning: parts of the map are deleted if you specify a size that is smaller than the original size of the map.
Tools->Brush A mark appears in front of this menu item if you select it. If this item is marked, a mouseclick in the mapbox changes a single tile to the current tile.
Tools->Flood Fill A mark appears in front of this menu item if you select it. If this item is marked, a mouseclick in the mapbox changes a region of the same tile to the current tile.
Tools->Select rectangle Let's you select a rectangular area of the map by dragging the mouse. The selection is only one layer high.
Tools->Map Screenshot Draw the entire map (not just the visible part) to a single bitmap. You are then asked for a location where to save this bitmap.
Help->Contents Show this text
**Help->About Show copyright information
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.
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.
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.
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".
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.
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.
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
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.
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.
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
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);
The tegel package comes with a set of examples to help you get started quickly.
shows how to display an animated tilemap, and how to do scrolling
shows three different ways to store tilemap and tilelist data on disk: in separate files, in datafiles or in the same datafile.
rotated tilemap example
displays information about a tilelist
mode7 tilemap example
(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:
type 1. each tile is a separate bitmap object
type 2. each tile is a RLE sprite object
type 3. all the tiles are on a single large bitmap. The bitmap is divided in tiles using a grid the tile in the upper left corner is tile 0, and right next to it is tile 1, etc.
type 4. same as 3, but rather than using left to right, up to down ordering, the order of tiles can be specified using indices. This can be useful for making animated tilesets.
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.