2D Tile Based Game -- Map Format

Started by
6 comments, last by Steven 19 years ago
Hello, i'm building a small scale 2d smooth scrolling game..currently i'm working on the map editor and am curious to see if my map format is as good as it could be..currently I have it like this

struct TileData 
{
int BackGround; //Layer 1 --Behind Everything
int BackGround2; //Layer 2 --Behind Everything except layer 1
int BackGround3; //Layer 3 --Last layer before the actual characters
int ForeGround; //Layer 4 --This layer would appear in front of the character
int ForeGround2; //Layer 5 --Layer ontop of Layer 4
int Roof; //Roof Layer, this layer will disapeer when a character walks into a building
int Attribute; //warp, door, wall, key..you name it
int Zone; //what monster, music, friendly, indoors? 
};

struct MapData
{
char MapName[128]; //name of the map
TileData Tiles[128][128]; //128x128 maps
//maybe more stuff?
};



And that's basically my map format as of now..my tiles are all located on a bitmap, and are all numbered I'm not sure if I have too many layers to be able to make a smooth scrolling game...or will that be to much for the computer to handle that fast? My drawing routine maybe a little shaky as well..it goes similar to this..

for(int x=0; x<=12; x++)
{
for(int y=0; y<=12; y++)
{
DrawLayer1(x, y);
DrawLayer2(x, y);
DrawLayer3(x, y);
DrawCharacters(x,y);
DrawLayer4(x, y);
DrawLayer5(x, y);
DrawRoof(x, y);
}
}
so Yeah, I would appreciate it if you guys told me what you think of that, or any enhancements or corrections or ideas you might have..Thanks :-) ArchG
Advertisement
OK so just to get this into my mind correctly your map file has the following:

fixed maximum size for file name 128 chars without the extention
fixed map seize 128x128.

Ok now that sorted a couple of questions:

How many tiles do you have in each layer?
Why do you need 3 background layers?
Does your tiles have transparency?

Going off your map format 1 map file will be 128 * 128 tile = 16384 tiles (16K tiles)
1 tile = 8 * 4 = 32 bytes ( 1 int = 4 bytes IIRC ) = 524228 or 512Kb

Thats half a meg of memory for storing a single map.

If your limiting your tiles to 256 per level, and had a maximum of 255 zones, then you can drop the amount of memory down to 1/4 that size by using char's or BYTE sized variables (approx 128k)

now onto your drawing code, yes this could be optomised, if you are not allowing your tiles to have transparency then you can do a simpler draw cycle, if your not in the zone then draw the character and roof layers only, if your in the zone draw the background, char and forground layers. Also limiting to only drawing tiles that would be visible to the screen would make the game draw the world faster, thus giving more time to AI and other mechanics.

if you are allowing your tiles to have transparency then your stuck drawing everything on every visible tile.

How I do my 2D tile maps is:

My layer - Your Layer

Background bitmap - Layer1
Floor Tiles - Layer2
Characters - Chars
Forground - Layer4
UI - UI

I've not donw any top down with roofs yet, but they would be drawn just before the UI level, in total only 4 levels would be saved (the last / missing level would be objects).

The more layers you have to draw, the more overdraw you create, which in turn will cause your game loop to slow dowm, try and remove some of the unneeded layers, as I previously said why 3 backdround layers? why 2 forground layers?
When I find my code in tons of trouble,Friends and colleages come to me,Speaking words of wisdom:"Write in C."My Web Site
I might not be understanding how much info is stored in your bitmap, but why not parse your levels into a text file? Thats what I did for my tile editor, it supports up to 100x100 size maps and the file size per map is less than 50k.

Other than that suggestion, all I have to say is why so many backgrounds? It would probably be more efficient to just draw the 3 background layers into the image than actually have 3 physical layers unless you are doing something like parralax scrolling.

Besides that , it looks pretty good to me.
My Current Project Angels 22 (4E5)
Thank you for your responses...

Quote:
How many tiles do you have in each layer?


Hmm, I'm not sure if I understand this question right..but with the fixed size of 128x128 there would be about 16k tiles in every layer..(if they were filled)

I will have no background bitmap or anything, so everything is made completely in tiles

Quote:
Why do you need 3 background layers?


I guess I just thought that with 3 background layers I could make the maps look very nice...for example in layer 1 (BG1) I could have my grass...then in layer 2 (BG2) I could have some rocks or mushrooms or flowers or something over top of the grass..and then in BG3 I could put the bottom of a tree down..making it look like a tree with some flowers and grass behind it..
3 maybe too many though, i'll most likely take out a BG layer..

Quote:
Does your tiles have transparency?


All layers have transparency except for the ground layer, the very bottom layer..making it so you can stack things and kindof emulate some 3d i guess...

So yea, if that is to many layers and to many tiles and such, I might have to get rid of some of them, I would like to be able to maintain a good 30-35 fps and still have some left over throttle incase I still wanna do some other stuff

I also like the idea of using chars instead of ints..but if the map is smaller than 1 mb I didn't think it would really be a big deal anyway,as it would all be loaded into memory at runtime..but if that becomes an issue (it probably will) I was thinking about using chars or maybe bit fields with my structs

Thanks alot for the input guys

In my 2d tile editor/game i have a separate layer class.

Each layer holds a dynamic 2d array of tiles (may be different throughout) and has a speed factor (allowing for parallax).

Each level map consists of a std::list of layers making it easy to have less or more. Usually there's one extra layer for collision tiles. This makes it possible to have for example passable walls that look like solid ones.

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

I've just written a 2D top-down tile rendering engine similar to what Endurion suggests, using linked lists.

I started off in a similar fashion to you and had an array that was filled with ground tiles, if I wanted a flower then my bitmap would contain tiles that had the ground and the flower. THis led to loads of tiles and my artistic ability let me down. I then wanted an OVER layer so the characters could walk behind them. However, I didnt want an OVER layer on every tile, meaning that most of my OVER layer was redundant and just taking up space.

Using linked lists completely circumvents redundant tiles and also allows flexibility in the amount of graphical data on each tile. There is an article somewhere in the Resource section that completely describes this technique, here is a brief summary in case you are not familiar:

You start with an array (lets say 128x128, as in your case) but instead of the array holding graphical data it holds data on the properties of the tile (attribute, zone etc.) and it also holds a linked list of all the tile graphics to display on that tile. In a simple form:

Map[0][0] ---> List Header ----> List Node ----> List Node ----> NULL;
Map[0][1] ---> List Header ----> NULL;

In this example, the array elements (at the start) hold property data and a pointer to the List Header. The List Header is nothing more than a list node and there is always a header as there is always a background layer (BG1 in your case). Each node ONLY holds a pointer to a 'tile graphic' structure, which describes how the tile shoudl be drawn to the screen (i.e. texture, size, masking etc.).
Each array element will always have one node (BG1) and can then contain any number of subsequent nodes. Meaning that some tiles can have 10-20 (!) layers whereas others may only have 1 and you are using only as much memory as is required.
In this example, Map[0][0] could contain a grass floor, a flower and a tree, whereas Map[0][1] only contains a grass floor.


If your ability with lists is good then I would definitely adopt this strategy, if your knowledge of lists is shaky then learn and adopt this technique!
I've just moved onto this from where you are now and I guarantee the nuts and bolts are identical, its just that this method slashes your memory usage to almost a bare minimum for your needs.

If you cant find the article then I have it on disk somewhere and could dig it out and send it to you if necessary.

Hope this helps, sorry for being long-winded if this theory is known to you.
The article is tile based techniques by Jason McIntosh
Quote:Original post by ArchG
Thank you for your responses...

Quote:
How many tiles do you have in each layer?


Hmm, I'm not sure if I understand this question right..but with the fixed size of 128x128 there would be about 16k tiles in every layer..(if they were filled)

I will have no background bitmap or anything, so everything is made completely in tiles


No what I meant was how many different tiles does your map support..

No even that reads wrong :D

OK you said you have a grass tile, and I'll assume some other tile images (grass, mud, water, etc), how many different tile images do you have for each layer?

As furiousuk haas sugested, using linked lists for your map storage in memory would be a better way to do the storage. Also when you make your stuct to store your tile information make sure it's doubleword aligned and that it is in total a multiple of 4 bytes (using pure int's your fine, using bytes add some filler bytes to make up to the 4 byte multiples) as this will speed up access time to the tile info. Also count any pointers as 4 bytes (IIRC a pointer is a 32 bit value)

Also final sugestion for the layers - make a new map and a test program that displays your different layers as an on/off with real time FPS counter, this way you can see how many layers you can handle, if you can code that up and uploadit somewhere with instuctions (press 2 to turn on/off layer 2, etc) I'm sure some of the members of GameDev will try it out (hell even crappy grafix will be fine for this test of your engine), this way to can see if the 6 layers are too much, and if you leave the code in place for the optional layer drawing, then you can make the final product dyamically draw the layers depending on the FPS of the end PC, slower PC = less layers, fast PC = more layers drawn, just make sure that you have some of the layers set to alway's on...
When I find my code in tons of trouble,Friends and colleages come to me,Speaking words of wisdom:"Write in C."My Web Site

This topic is closed to new replies.

Advertisement