Index:
Welcome
Disclaimer
Requirements, how to use
About the Mappy DLLs
dxdemo1, the example
dxdemo2, the example
Using MappyDX with the CDX games library
Blt, BltFast, Clippers etc...
Mappy API:
Mappy API reference
MapLoad (char * , LPDIRECTDRAW);
MapDecode (unsigned char * , LPDIRECTDRAW);
MapFreeMem (void);
MapInitAnims (void);
MapUpdateAnims (void);
MapDraw functions
MapDrawRow (LPDIRECTDRAWSURFACE, int, int, int, void (*cellcall) (int, int, int, int));
MapRestore (void);
MapGenerateYLookup (void);
MapChangeLayer (int layernum);
MapGetBlockID (int blid, int usernum);
MapLoadMAR (char * filename, int layer);
MapDecodeMAR (unsigned char * marmemory, int layer);
MapGetBlock (int x, int y);
MapSetBlock (int x, int y, int layer);
MapGetXOffset (int x, int y);
MapGetYOffset (int x, int y);
MapCreateParallaxSurface (LPDIRECTDRAW);
MapDrawParallax (LPDIRECTDRAWSURFACE, int, int);
MapRestoreParallaxSurface (void *, int);
MapReleaseParallaxSurface (void);
Troubleshooting
Hints and tips
Version History
This code library provides functions to access and display
FMP maps made by the Mappy tile map editor. Use of this library is
free and you may modify it as you like, it would be nice to get a
credit and link to the Mappy site if you use it in your game, but
that is up to you. The previous version was tested with Visual C++
4.0, Visual C++ 5.0 and Borland C++ 4.51 with various DirectX SDK,
I have only been able to test this version with MingW32.
If it doesn't work on your compiler and you think it should, let me
know immediately and I'll fix it! For changes since release 2, see
the version history.
Please take the time to look at this documentation.
If you want to contact me, please email me at
mappy@tilemap.co.uk.
Mappy homepage. The current Homepage for Mappy is:
http://www.tilemap.co.uk or
http://www.geocities.com/SiliconValley/Vista/7336/robmpy.htm
or if all else fails: http://surf.to/mappy
This software and associated files are provided 'as is'
with no warranty or guarantees of any kind, you use them at your
own risk and in doing so agree that the author is in no way
liable and cannot be held responsible for any loss of
time/data/hair or anything else that may occur either directly or
indirectly from the use of this software or associated files.
Sorry about that, but I don't think it's fair that I get
sued for something I release for free, just remember to keep
backups and you'll be fine. I have never lost any data or files
or had Mappy screw anything up, just be aware that if it does I
can't be held accountable :)
You will need a PC with a C++ compiler that supports and
has installed the DirectX SDK version 3 or later, you will also
need this library and the Mappy editor (to make your FMP files). You will need
to include the file 'mappydx.cpp' in the list of files that are in your
project, and include the file 'mappydx.h'
in any source files that need to call Mappy functions. Alternatively you can use the DLL (by using the file mpydll.h).
Use of the library is through a simple API (see
Mappy API reference), and the easiest way to see how it works is
through the included example dxdemo1, as described in the next section...
After you have initialised DirectDraw, you pass the DirectDraw object
and the name of the map file to the Mappy function 'MapLoad', or the DD object
and the memory address of the FMP data to 'MapDecode', if it is successful,
you can then call MapInitAnims (); then go into your gameloop, inside which you
can call MapUpdateAnims (); and the MapDraw functions. Should you lose your
surfaces and need to restore them, call MapRestore (); When you've finished
with the map, call MapFreeMem to remove it from memory. It's that easy.
In response to requests to be able to use MappyDX from non-C++ languages
I have put MappyDX in a DLL. To use it from C or C++ is fairly simple, just #include
"mapdll1.h", make a .lib (from the .dll and .def) and use it normally. For other languages you should look for downloads
from their pages, or make your own (I know there is one for DelphiX, for example).
There are a few important differences between mappydx and mappydll. First,
you must know which version of the DD interface your language is using. MappyDX1.dll
uses interface 1, MappyDX4.dll uses interface 4, if you need a different one, let me
know and I'll compile it. Second, the #defines in MappyDX are replaced by functions:
void MapSetDrawArea (x, y, width, height); //Default is 0,0,640,480
void MapSetParaSize (width, height); //Width and height of parallax
void MapSetPalette (LPDIRECTDRAW, LPDIRECTDRAWSURFACE); // Sets palette in 8bit (after MapLoad)
void * MapGetPtr (int); //does nothing yet
int MapSetPtr (int, void *); //does nothing yet
int MapGetVal (int); // Use this to READ vars, see the MPY_ defines (1 to 17 only) in the .h files, example:
mymapwidth = MapGetVal (MPY_MAPWIDTH); // Get the mapwidth (after MapLoad)
int MapSetVal (int, int); // Use this to WRITE vars, these MPY_ vals only:
MapSetVal (MPY_BLTTYPE, 0=BltFast 1=Blt(default));
MapSetVal (MPY_MEMTYPE, 0=Vidmem then Sysmem (default) 1=Sysmem); // Before MapLoad
MapSetVal (MPY_8BITTOPINK, 0=No conversion 1=Convert (default)); // Before MapLoad
Don't be put off by the amount of code in dxdemo1.cpp (about 350 lines)
as most of it is just setting up Windows and DirectDraw, there are only about 20
lines directly related to Mappy. First, note that mappydx.h is included:
#include "mappydx.h"
This is needed to access any of the Mappy functions. The next point of interest
is line 366, the Mappy function 'MapLoad' is used to try to load the map,
DirectDraw must have already been started, and if you are loading a high/true
colour FMP onto an 8bit display you must have set the palette too. If you are
using Visual C, be aware of the current directory, it may not be the same as the
one with the executable in when you run it from DevStudio. At line 375,
the Mappy structure mappept is used to set the palette, this is only valid for
8bit FMP files after they have been loaded. GameInit is called which calls
MapInitAnims (); which resets the animations to their starting positions. In
the main gameloop, simply call MapUpdateAnims (line 120) to advance the anims,
then the MapDraw functions you want to use. If you want to draw sprites between
the background and foreground, simply draw them between the calls to MapDrawBG
and MapDrawFG. If you want to draw the background transparently, call MapDrawBGT
instead of MapDrawBG.
You will need to add mappydx.cpp to your project files, you will also need
to adjust the defines in it if you don't want the defaults. This is particularly
important if you are supporting more than one resolution. To do it,
open mappydx.cpp and find near the top the small section of #defines that
you can change. You can either change these to other fixed values, or to variables.
The advantage of defining to variables is you can change things in runtime, example:
#define MSCRW screenw
#define MSCRH screenh
will make MappyDX use those variables instead of fixed values, you can then declare
them as external (if you are keeping them in another source file):
extern int screenw;
extern int screenh;
This is exactly how I did it for the MappyWin32 editor where you could set your
screenmode and load in a map with any sized tiles.
To compile the example, make a new project and add the files dxdemo1.cpp,
dxdemo1.rc, mappydx.cpp, and ddraw.lib. Make sure all those files are in the same
directory along with mappydx.h, mylogo.bmp and myicon.ico and also the FMP file you are going
to use. You should now be able to compile and run the example, if you can't, see the
Troubleshooting section.
I have now added parallax functions (release 5) and dxdemo1 has been
altered to use them (fullscreen only).
Same as dxdemo1, but for Isometric, uses MapDrawRow, to depth sort everything. It uses
the same BMP as demo1, so the title etc is wrong.
To compile the example, make a new project and add the files dxdemo2.cpp,
dxdemo1.rc, mappydx.cpp, and ddraw.lib. Make sure all those files are in the same
directory along with mappydx.h, mylogo.bmp and myicon.ico and also the FMP file you are going
to use.
Note: An add-on class called CDXMappy is available at the CDX site which should offer a more 'C++' way of displaying maps.
I was asked to add support for CDX in MappyDX, and you can use it if you change
some defines, but CDXMappy is much nicer to use.
CDX's homepage is currently http://www.cdxlib.com
CDXMappy is currently on the main mappy site
One thing I didn't realise until recently was that BltFast (the method MappyDX used to use to draw the tiles to your surface) does NOT work when you have attached a DirectDraw clipper. Because of this, you can now tell MappyDX to use Blt or BltFast, this is a define in the user settings at the top of mappydx.cpp. Also, I have added the option for you to specify system memory instead of video memory for the tiles. This is achieved by changing the RBCAPS_TYPE define in mappydx.cpp, setting it to system memory also requires that you use Blt (BltFast only works on video memory). I would only recommend having tiles in system memory if you are rendering to a system memory surface, otherwise it will be a lot slower.
In summary, leave it as default (using Blt and video memory) unless you know you need a different system.
There are currently only a few functions in the Mappy API, but you can also
access variables, they should be self explanatory, but see the Hints
and tips section for a few hints. This release has full FMP1.0 support.
int MapLoad (char *, LPDIRECTDRAW);
Loads the map with the path and name specified into memory so it can be used, this
function or MapDecode must be used before calling other Mappy functions.
Returns 0 on success, -1 on failure.
int MapDecode (unsigned char *, LPDIRECTDRAW);
Same as MapLoad, but you pass the memory address of FMP data instead, this can be
useful if you store the map in a compressed file, this function or MapLoad must
be used before calling other Mappy functions. Returns 0 on success, -1 on failure.
void MapFreeMem (void);
Frees the current map and all associated memory and surfaces Mappy is using.
void MapInitAnims (void);
Resets animations to their initial values.
void MapUpdateAnims (void);
Increments animations.
int MapDrawBG (LPDIRECTDRAWSURFACE, int xoff, int yoff);
int MapDrawBGT (LPDIRECTDRAWSURFACE, int xoff, int yoff);
int MapDrawFG (LPDIRECTDRAWSURFACE, int xoff, int yoff, int gfxlayer);
These functions all draw to the surface specified, and at the
x and y offset given, for example, if you call MapDrawBG (lpDDSBack, 1000, 2000);
the area of the map 1000 pixels from the left edge and 2000 pixels from the top
will be drawn to the lpDDSBack surface. The size and positioning of drawn area is
dependant upon what MSCRW, MSCRH, MMOX and MMOY are defined as (alter these settings at the top of mappydx.cpp), if they are
variables, make sure they are correct before calling these functions. Attempting
to draw outside the surface, or an area outside the map will probably shutdown
the program. So don't do it :) MapDrawBG draws the BG layer without transparency,
so it will completely overwrite the specified area. MapDrawBGT draws the BG layer
with transparency, any 'block 0' or pixels of the transparent colour won't overwrite
the area you are drawing. MapDrawFG is the same as MapDrawBG except for FG layers,
you specify 0, 1 or 2 as the last paramater for the FG layer.
int MapDrawRow (LPDIRECTDRAWSURFACE, int xoff, int yoff, int maprw, void (*cellcall) (int, int, int, int));
Same as MapDrawFG, except:
int maprw is the row to draw
cellcall is a callback function for each cell, pass NULL if you are doing your
own depth sorting, or using another system.
See dxdemo2.cpp for an example of this.
void MapRestore (void);
If you lose your surfaces (for example if someone alt-tabs), you can call
this function to restore them.
int MapGenerateYLookup (void);
This is optional, call this after MapLoad or MapDecode (or variant) and
it will generate a lookup table that _may_ slightly speed up the functions
MapGetBlock and MapSetBlock, and allows you to use the maparraypt. If you
use this, you _must_ use MapChangeLayer if you want to swap between layers.
Another advantage is you can access block or anim offsets simply with:
maparraypt[y][x];
Where x is the offset from the left in _BLOCKS_, and y is the offset from
the top in _BLOCKS_. Note you can get the actual block structure with the
functions MapGetBlock and MapSetBlock.
The memory allocated is freed when either MapFreeMem is called, or another
map is loaded.
int MapChangeLayer (int layernumber);
This changes to a different map layer, returns -1 if failed, or the new
layer number (0 to 7) if successful.
int MapGetBlockID (int blid, int usernum);
*nbsp; returns the number of the first block that matches 'blid' in the field
specified with usernum (1 to 7, user1 to user7). If no match, returns -1
int MapLoadMAR (char * filename, int layer);
int MapDecodeMAR (unsigned char * marmemory, int layer);
Loads a .MAR file into a specified layer. Decode does it from memory,
you can dealloc that memory afterwards. If you called MapGenerateYLookup,
call it again after this function. Returns -1 on error, 0 on success.
BLKSTR * MapGetBlock (int x, int y);
Returns a BLKSTR pointer, useful for collision detection and examining a
blockstructure. Note: the x and y paramaters are the offset from the left
and top of the map in _BLOCKS_ NOT pixels. Example:
BLKSTR * myblkstr;
myblkstr = MapGetBlock (xoffinblocks, yoffinblocks);
if (myblkstr->tl) { top left collision is set for this block }
MapSetBlock (int x, int y, int strvalue);
The x and y paramaters are the offset from the left and top of the map
in _BLOCKS_ NOT pixels. If strvalue is
positive, the cell is set to that block structure. If strvalue is
negative the cell is set to that anim structure-1 (ie if you want to
put anim 3 in, strvalue would be -4).
int MapGetXOffset (int x, int y);
int MapGetYOffset (int x, int y);
Returns the X or Y offset in blocks of the specified pixel coordinates.
This is very useful on maps with non-rectangular blocks as it is pixel perfect.
MapCreateParallaxSurface (LPDIRECTDRAW);
Creates a surface for the parallax graphic of the size PARAW*PARAH.
These are defined in mappydx.cpp, you must call this before using the
other parallax functions. Remember to draw the graphics afterwards using
MapRestoreParallaxSurface. Note that the surface is freed on a call to
MapLoad, MapDecode or MapFreeMem.
MapDrawParallax (LPDIRECTDRAWSURFACE, int, int);
Efficiently draws to areas that will not be obscured by layers
above it (minimal overdraw). The x and y coords passed should be the
SAME as to MapDrawBGT etc, these are automatically halved. The parallax
surface will be tiled over the surface. Remember to use MapDrawBGT
instead of MapDrawBG if using this function. Be sure your map has the
transparency bit set for any blocks with transparent pixels in them
(especially block 0). This only works with rectangular tiles.
MapRestoreParallaxSurface (void *, int);
Call this after calling MapCreateParallaxSurface to render
the parallax graphics, also call if MapDrawParallax returns -1. If you
pass NULL as the source, it's assumed you have blitted the parallax
bitmap to lpDDSParallax.
void MapReleaseParallaxSurface (void);
Frees the parallax surface, you shouldn't normally need to call
this as it is called by MapFreeMem.
Don't worry if you get messages like 'may lose significant digits', when
compiling mappydx, that's normal.
If you get messages like 'unknown type _LPDIRECTDRAW' you haven't got your
DirectX SDK setup properly on your compiler, make sure ddraw.lib is in your project files.
If you keep getting 'can't load map' messages on the demo, ensure you have a
compatible FMP file in the same directory as you are running from, and it has the
same name as needed in dxdemo1.cpp
If your programme exits or crashes when you try and draw a map, make sure
you have changed the defines at the top of mappydx.cpp
If you are loading an 8bit map onto a high colour screen, make sure the
transparency colour is defined correctly, see hints and tips below for a useful idea
Although you can still change the map array layer by doing:
mappt = mapmappt[layer]; where layer is a VALID layer number.
There is now a function called MapChangeLayer which you should use instead, in fact
you must use MapChangeLayer if you have called GenerateYLookup
If you are loading an 8bit map to a high or truecolour screen, the
transparency index will be changed to the truecolour value. If you don't want
this behaviour, change the RB8BITTOPINK define in mappydx.cpp or change the 24bit
colourkey to 000000 in MappyWin32.
A collision detection example is now given in
MapGetBlock
Release 11B:
Fixed error in MapDecode
Release 11:
Fixed incredibly insignificant accuracy error in 15bit loader (no noticeable effect)
New map for dxdemo1 (TEST2.FMP, better size blocks)
Release 10:
Small fixes and tweaks
Examples show windowed mode
You can specify the left or right side of a pillar with bits 2 and 3 in 'others'
Release 9:
Small fixes and tweaks
Mappy in a DLL!
Release 8:
MapDrawRow function and dxdemo2 example
Release 7:
Many many changes inc:
Full FMP1.0 support
100% accurate 15/16bit to other conversion (no more 0xF800F8 :)
Non-square tile support (Iso, hex etc)
Release 6:
You can specify where to store the tiles (system or video memory)
You can use Blt instead of Bltfast if you want
Release 5:
Added 4 efficient (minimal overdraw) parallax functions
Release 4:
Fixed function MapDecode (wasn't working before)
Added MapGenerateYLookup, MapChangeLayer, MapGetBlock and MapSetBlock functions
Added #defines to mappydx.cpp to allow specifying a version of a DirectX interface
Added support header and example for CDX
Release 3:
Much faster loading of graphics to surfaces
Can now use tiles whose widths are different to height
All colourdepth conversion
General tidying up
Decent documentation
Release 2:
structsize fix for Visual C compilers
Release 1:
Original version, pretty good for a first release
This documentation is for MappyDX Release 11B by Robin Burrows 7/5/2002.