Presto - A tilemap library for use with the Allegro game programming library
Copyright 2008 Peter Fernandes 


--Introduction--

Presto is a general-use tilemap engine coded in C that uses Allegro for graphics rendering, and
therefore is intended for use in games using Allegro.  It can handle rectangular tiles of any height
and width (and different height from width), animated tiles, transparent tiles, loading tilemaps
from files, and the capability to change most of these elements on the fly.  Presto uses the
loadpng library (http://tjaden.strangesoft.net/loadpng/) to load tiles in PNG format.



If you're reading this file, you're probably interested in either installing this library, or
how to use the engine in your on program.  If the former, read the INSTALL file located in the
same directory as this README file.

The directory "test" contains a test program using some of the functions in this library.  It can be
compiled using the build script.


--Using Presto--

In order to use Presto with your program, you need to include "presto.h" in all relavent source
files.  You also need to link with libpresto and liballeg.  An example GCC call using Presto:

gcc -Wall -Os -o myprogram `allegro-config --cflags --libs` -lpresto main.c


Here is a basic outline to using the engine:

1. Initialize Allegro
	This means at the very least calling:
		-allegro_init()
		-set_color_depth()
		-install_timer() If you are going to use animated tiles
		-set_gfx_mode()
2. Load a tilemap from a file using load_tilemap), or use the engine functions to fill the
	TILEMAP struct yourself.  Loading from a file is HIGHLY recommended as it greatly simplifies things,
	and makes it easy for users of your program to change the tilemap.

3. Call install_tilemap() if you want to use animated tiles.  If you are only using static tiles,
	install_tilemap() does not need to be called.

4. Now you are ready to render your tilemap.  Do this using render_tilemap().  If using animated tiles,
	update_anim_tiles() should be called before every rendering so that tiles will animate properly.

5. When done using your tilemap, call free_tilemap() with your TILEMAP struct to free the resources that
	Presto allocates for the tilemap.  Call uninstall_tilemap() when done using the engine if you
	are using animated tiles.


--Function Descriptions--

NOTE: Only functions useful to the engine usage are listed here.  Other functions, like those used internally
by the library are not listed.

-
char *tilemap_get_err(void);
-
	Returns a pointer to a string describing the last error thrown by Presto.  The error string is updated
	every time a Presto function errors.


-
int install_tilemap(TILEMAP_LIST *list);
-
	Sets up the Allegro timer used by Presto for animated tiles.  list is a TILEMAP_LIST struct * that contains
	all the tilemaps you are going to use (more than one perhaps for layered effects), AFTER being loaded with
	load_tilemap().  Returns 0 on success, <0 otherwise. This must be called before using the engine if using
	animated tiles.


-
void uninstall_tilemap(void);
-
	Frees the timer allocated by install_tilemap.  Must be called at the end of the program.


-
int load_tilemap(char *filename, TILEMAP *tilemap);
-
	Loads tilemap data from a file into a TILEMAP struct.  The file format is described later in this file.
	Returns 0 on success, <0 on error.


-
void free_tilemap(TILEMAP *tilemap);
-
	Frees data associated with the tilemap.  This must be called at the end of the program if the tilemap
	was loaded with load_tilemap() (or manually with other functions).


-
void render_tilemap(BITMAP *dest, TILEMAP *tilemap, unsigned int x, unsigned int y, unsigned int width, unsigned int height, int angle, int scale, int off_x, int off_y);
-
	Renders a tilemap to the destination bitmap dest with a negative offset of x and y horizontal and vertical pixels
	respectively.  width and height define how many tiles to draw horizontally and vertically, respectively.  angle
	controls the rotation of the tilemap around its center, and is an integer with 0 being 0 degrees clockwise, and
	256 being a full circle.  eg. 64 would be equivalent to 90 degrees.  Scale is a fixed-point integer that determines
	how the rendered image will be scaled about its center.  256 is equivalent to 1X, 512 to 2X, 128 to .5X, etc.
	off_x and off_y allow the tilemap image to be shifted once it is rendered.  This can be useful when drawing a
	scaled-up tilemap to scroll over portions of the tilemap that become hidden due to the scaling, when changing x or
	y would cause the tilemap to go out of bounds.


-
void update_anim_tiles(TILEMAP_LIST *list, unsigned int x, unsigned int y, unsigned int width, unsigned int height);
-
	Updates animated tiles in each tilemap in list within a rectangle defined by the top-left corner, (x,y), with the
	specified width and height.  This way, animated tiles can be updated, for example, only when a player scrolls to
	where the tile will be shown, not wasting time updating tiles that are not shown.


The following functions may be used either to load a tilemap with data when loading from a file is not practical,
or to change tilemap data on the fly while the engine is running.  To understand these functions, you need to know
about how a tilemap is stored in the TILEMAP struct.  Further down in this file is a description of the internals
that should be read.


-
void tile_change_anim(TILEMAP *tilemap, unsigned int x, unsigned int y, int id);
-
	Changes the animation sequence of the tile at position (x,y) in the map to id, and resets the animation index
	to zero, starting the new animation at the beginning.  Setting id to -1 stops animation (follow up with a call
	to tile_change_index() to effectively change from an animated tile to a static tile of your choice).


-
void tile_change_index(TILEMAP * tilemap, unsigned int x, unsigned int y, unsigned int index);
-
	Changes the animation step (frame) that the tile is on, if that tile is animated.  If the tile is static,
	tile_change_index changes the tileid of the tile with id corresponding to a pool entry.  This function has
	no effect if the tile is synced to the frameclock.


-
void tile_set_loop(TILEMAP * tilemap, unsigned int x, unsigned int y, int loop);
-
	Changes the loop parameter for an animated tile.  Set loop for -1 for infinite loop, 0 to stop looping, or X
	where X>0 to loop X times.


-
void tile_set_sync(TILEMAP * tilemap, unsigned int x, unsigned int y, int sync);
-
	Sets whether the tile should sync with the frameclock.  sync==0==No, sync!=0==yes


-
void tile_set_trans(TILEMAP * tilemap, unsigned int x, unsigned int y, unsigned trans)
-
	Sets the transparency level of the tile against the background.  255==opaque, 0==transparent,
	-1==read alpha channel from file (does not work with BMP files) -2==ignore transparency.  It is
	very important to keep tiles that do not use transparency with a trans value of -2, as Allegro's
	blending functions are much slower normal sprite routines.


-
int tilemap_change_anim(TILEMAP *tilemap, int index, unsigned int *order, unsigned int *delays, int loop, unsigned int count);
-
	Changes an animation sequence corresponding to index currently stored in the tilemap or adds a new
	one if index <0.  count is the number of frames in the new animation. Returns the index of the new
	animation in the animation list or -1 on failure.


-
int tilemap_change_bitmap(TILEMAP *tilemap, int index, char *filename);
-
	Changes a bitmap at index in the pool, or adds a new one if index <0. Returns the index of the
	bitmap or -1 on failure


-
int tilemap_create_dims(TILEMAP *tilemap, unsigned int h, unsigned int w);
-
	Sets up the dimensions of a tilemap, allocating space for each TILE element in tilemap->map.
	Returns 0 on success, <0 on failure.


--Presto Internals--

If you want to initialize a tilemap yourself for some reason (loading from a file is HIGHLY suggested), you'll
need to know how information in the TILEMAP struct is used to render a tilemap.  I'll only explain enough
here to allow a user to initialize a tilemap using the library functions provided.

The first step to setting up a tilemap is to allocate space for the map itself.  This is done by calling
tilemap_create_dims() with the desired width and height in tiles of the tilemap.  Once the tilemap is
initialized using tilemap_create_dims(), you have access to each tile in the tilemap.

Next, fill the pool with the bitmaps that you'll want to use for your tileset.  Each bitmap must be of
the same height and width of the tiles.  The pool is where all your tile images reside.  Each pool entry
(Allegro BITMAP *) has an id that corresponds to its location in the pool.  eg. the first BITMAP * has an
id of 0, then 1, etc.  To add bitmaps to the pool (or change them later), use tilemap_change_bitmap() for
each bitmap you want to add or change.

Now we'll talk about animation.  If you are using animated tiles, you need to know a bit about how Presto
handles them.  There are three basic parts to a Presto animation: frame order, the delay between each frame,
and how the animation will loop.  Once an animation sequence is created, it can be shared among all tiles,
so more than one tile can use the same animation.  To define a new animation sequence, call tilemap_change_anim()
with the index parameter set to -1.  tilemap_change_anim() will return the "animation index," or the animation
number of the newly created animation.  This can be used to change the animation later, again with
tilemap_change_anim().  The order parameter calls for an array of unsigned ints that refer to bitmaps in the
pool.  This determines what each frame of the animation will look like.  The delays parameter is similar, and
defines how much time, in ms, should pass before the next frame in the sequence is shown.  The loop parameter
can be -1 to make the tile loop infinitely, 0 to play only once, and any integer X > 0 to loop X times.
Tiles only loop while they are being updated (see update_anim_tiles()).  The count parameter is the number
of frames in the animation, and should be exactly the number of elements in order and delays.

Now, what happens if we want all tiles to animate together (like the question blocks in Super Mario Bros.),
but they come into the update rectangle at different times, therefore beginning animation at different
times?  Well, Presto has an animation frameclock to which all tiles can sync.  To sync a tile to the
frameclock, call tile_set_sync() with a sync value of 1, where your tile is at (x,y) in the tilemap.  This
will assure that all tiles connected to the same animation sequence will animate together.  All tiles connected
to the frameclock initialy have the same loop value, but this can be changed with tile_set_loop().

A tilemap would be nothing without tiles, so the next step is to define what each tile should do.  If static,
the only step is to set which bitmap from the pool the tile will display.  This is done using tile_change_index().
If the tile is animated, you need to give it an animation id to follow using tile_change_anim(), and decide
whether it should sync to the frameclock or not.  Whether or not the tile should sync is undefined at first, so
a call to tile_set_sync() is necessary.  A default loop value is given to the tile based on the one stored with
the animation sequence.


--Tilemap File Format--


Presto has the capability to load a tilemap from a text file of a specific format.  This is almost always the
way tilemaps should be initialized.  The format is as follows:

To begin, a Presto tilemap file is plain text.  The file extension doesn't matter, but a suggestion is to use
".map" to keep things simple.  Blank lines are ignored, and so is any line that begins with a hash character ('#'),
used for comments.  Every line that is not blank and does not begin with a hash character is considered to be a
data line.  There is a specific order to the appearence of each data line:

W,H        - The width and height of the tilemap. eg. "38,14"
W,H        - The width and height of the tiles. eg. "16,16"
X          - The number of bitmap file entries following this entry (the number of bitmaps to load into the pool). eg. "26"
[FILENAME] [TRANSPARENCY_VALUE]
[FILENAME] [TRANSPARENCY_VALUE]
...        - X filenames each on their own line pointing to bitmap files of the correct height and width.  After each
	     filename on the line is an integer to initialize the transparency value for the bitmap.  Each tile displaying
	     the bitmap will share this value.  A value of -2 tells Presto to draw the bitmap with no transparency, -1
	     means to draw using the alpha channel loaded from the, and a value of 0 or greater gives that alpha channel
	     value to every non-transparent pixel in the image.
Y          - The number of animation entries following this entry (the number of animations to load into the tilemap). eg. "2"
[FRAMECOUNT] [DEFAULT_LOOP] [INDEX],[DELAY] [INDEX],[DELAY] ...
- First, the number of frames in the animation then a space.  Next, the default loop value for the animation, and a space.
After that is the index of the bitmap in the pool that you want the tile to display when the tile is done looping.  Give a
value of -1 to default to the first tile in the animation.  What follows are pairs of bitmap index/delay time pairs to define
how each frame of the tilemap should behave.  Bitmaps have an index, or id corresponding to the order in which they appear
in the file.

eg:

4 -1 -1 11,500 12,150 13,50 12,150
3 4 1 5,100 6,200 7,300

Last is the tilemap definition itself.  Each tile entry is represented by an integer corresponding to a bitmap id of a bitmap
defined earlier in the file.  Tiles are separated by commas and any desired amount of whitespace.  To make the tile index
refer to an animation index instead of a bitmap index, prepend the integer with an 'A', or an 'S' if you want the tile to
sync to the frameclock (animate together with other tiles that use the same animation).

eg:

 0, 0, 0, 0, 0,
A0,A0,A1,A1, 5,
 7,10,11,12, 0,
etc...



--Contact--

Peter Fernandes
supersonicandtails@gmail.com
hypersonic12 on AIM
hypersonic on freequest.net IRC

Please contact me with any bugs or (competent) questions you may have about the library.
Some other projects along with Presto can be found at http://www.hypersonicsoft.org

