Allegro.cc - Online Community

Allegro.cc Forums » Game Design & Concepts » Input on tilemap file format

Credits go to CGamesPlay, Evert, GullRaDriel, Peter Wang, and Thomas Harte for helping out!
This thread is locked; no one can reply to it. rss feed Print
Input on tilemap file format
23yrold3yrold
Member #1,134
March 2001
avatar

I'm just going to throw it out there and ask for input. This has nothing to do with Monday; I'll tailor the tilemaps for that game after the code is done. I'm just trying to figure out how I should organize the file formats Mapslapper spits out for generic use; turned out I used Allegro packfiles in "pack" format and I can't open the old files in the new program anymore. Oh well, burns no one but me, gives me an excuse to overhaul the old format. :P I'm also having trouble checking other programs for reference; Mappy's file format spec seems hidden in the example programs. Not real convenient.

Basically I'm used to the "header" style like what .bmp uses; that's how the original Mapslapper did it. But I hear stuff about blocks and chunks with CRC checksums and I start getting a bit dizzy. So while I read up on file format design in general (and that alone seems to be flagging up concerns I never thought of) I figured I'd ask a bunch of guys who know tilemaps what they suggest. It'll need to hold image data (or optionally, NOT hold image data), animation info, multiple layers of maps, collision detection info, scripts, and probably a few other things I've forgotten. Consider this a brainstorming session; how should I play it? Any formats you think I should look at as a model for this? Hey, maybe the Mappy FMP format (or some other tile format I don't know) does it all and I should just use that spec, I dunno ...

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

GullRaDriel
Member #3,861
September 2003
avatar

I'm all for the header thing, and I wouldn't bore me that much for a map file format.

All the informartion need to be written in that file, so the order/encapsulation does not matter, if you are able to read them back.

"Code is like shit - it only smells if it is not yours"
Allegro Wiki, full of examples and articles !!

Thomas Harte
Member #33
April 2000
avatar

The problem with the "binary header implies format of all binary data to follow" style is that you get into increasingly murky waters when you want to expand it. Chunks are really good for that sort of thing, in that they're just like a whole bunch of tiny binary files all saved together in a line, so you can add or remove components without having to do a bunch of special branches in your file parser or write a whole bunch of documents that say things like "if file version is X, follow decoding instructions on page Y, otherwise follow decoding instructions on page Z".

I've been quite impressed with the PDF way of doing things, though it does require a bit more work on your part.

The main part of the file is made up of numbered objects. These are essentially like chunks; each has an ASCII header and then, sometimes, a 'stream' which may be encoded either in ASCII or a binary format (including a binary format filtered through zlib or some other compressors).

There is a huge cross-reference table which associates file positions with object numbers. This is stored at the very end in PDF files, so that when you're writing a PDF file you can work out file offsets empirically as you go then just dump them at the end — there is no need to keep the entire file in memory at any time.

One object is nominated as the head, it nominates its children, which depending on their types may nominate other objects that are part of their logic.

They achieve that in their ASCII headers, so it is trivial to add new features to the file format by adding new optional fields to the headers. All the heavy storage (in your case, actual pixel graphics) is left in the ASCII-or-binary-maybe-compressed streams.

Naturally there are various rules for parsing the headers, including standard syntax for compounded references (e.g. so that a page can be the composition of many streams of data).

I guess the main increase in complexity over the binary method is a tokeniser. But it's something to consider.

Peter Wang
Member #23
April 2000

Sounds like you actually want two formats: a hierarchical container for disparate objects, and the actual tilemaps. For the former, I suggest... a directory. With files. You can zip it up if you like. The latter, I'd recommend using some extensible text format (easier in most cases) and letting the compression algorithm deal with making it smaller.

23yrold3yrold
Member #1,134
March 2001
avatar

Wow. That sounds super complicated. :o What benefit is any of it?

I think I've pretty much decided my method. One short header at the beginning, followed by chunks (the chunks themselves have small headers describing the type of data in them, be they images, animation descriptions, map layout, etc) which terminate in an EOF chunk. Unless someone has some good reason why that shouldn't pretty much handle any given sort of tilemap data, I'm running with it.

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

Evert
Member #794
November 2000
avatar

I have to say, I like Peter's suggestion of a directory with files in it. I used to be a big fan of compact obfuscated user-defined file formats, these days I prefer text files. Directories are good too if you want hierarchical things. And indeed, if you insist on having it all in one file, you can just zip it up.

It's your format though, so go with what you think works best. One tip: if you give each chunk a header of its own, be sure to include the size of the chunk (mabye the size of the chunk and the size of the header, if the latter can vary) so that if you later decide to add stuff to the format, your older programs can simply skip data they don't need or understand. That's saved me quite a bit of headache on a number of occasions in the past.

Neil Walker
Member #210
April 2000
avatar

I couldn't answer because your avatar is so annoying I switched off :)

[edit]Brilliant! I can use adblock to remove just this avatar :)

Neil.
MAME Cabinet Blog / AXL LIBRARY (a games framework) / AXL Documentation and Tutorial

wii:0356-1384-6687-2022, kart:3308-4806-6002. XBOX:chucklepie

Thomas Harte
Member #33
April 2000
avatar

Quote:

Wow. That sounds super complicated. What benefit is any of it?

The cross-reference table is just a standard indirection table, with all the benefits of referring to things indirectly, i.e. you can adjust them and move them about without having to walk up a tree adjusting at least one and at most every other object that, eventually, refers to it. By relating object ids to actual file positions, it makes quick access easy. Always being a well-defined place makes the cross-reference table easy to find. Being at the end of the file1 means that PDF creation software doesn't need to keep much of the file at all in memory.

Splitting individual chunks into an ASCII part and a binary part is a pragmatic compromise that gives you one part that's easy to add or remove optional and mandatory fields from and one part that's really compact for more rigidly formed data.

I'll bet you end up needing a mechanism that allows one chunk to refer to arbitrarily many others. I guess the main simplicity you'll gain over PDF-style formatting is that you intend to load the entirety of every map file into memory at once, and then write it all at once. Which means you can make things implicit from positioning, e.g. have a map chunk that says "this map is composed of four layers" and then instead of saying "those layers are described by chunks a, b, c and d" you can just assume it means the next four chunks in the file.

Peter Wang's RISC OS/OS X—type directories are really smart; you could even flag them as bundles in the Mac realm so that they look and act like a single file in the Finder. It'd mean you could devolve all map and image data to common PNG files, for example. Then someone like me could reduce my map file size by throwing all of those through a PNG optimiser. And if a better PNG optimiser comes along, or the PNG file format is improved in the interim, your code needs no adjustment.

23yrold3yrold
Member #1,134
March 2001
avatar

Quote:

I used to be a big fan of compact obfuscated user-defined file formats, these days I prefer text files. Directories are good too if you want hierarchical things.

See, this is how my animation files work now, with a "text" file describing offsets and keyframes, etc. and the actual image data seperate, either in its own folder or in a datafile. And it strikes me as being about as obfuscated as you can get. I don't see the advantage yet.

The "directory" system some programs use actually kinda irritates me, because I feel like I have to hunt for what I'm looking for, and I would have to make a lot of allowances in my code for edits someone might make that messes up the "file". Someone may edit a picture innocently and suddenly it can't load the whole tilemap. Um, whoops? :)

I'm open to being sold on this; like I said, my animation system already does it. But the practicality of it seems to be going over my head. :-/ Wanna try again? :)

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

CGamesPlay
Member #2,559
July 2002
avatar

Quote:

See, this is how my animation files work now, with a "text" file describing offsets and keyframes, etc. and the actual image data seperate, either in its own folder or in a datafile. And it strikes me as being about as obfuscated as you can get. I don't see the advantage yet.

By separating your frames and control, you can easily edit individual frames, which may be an advantage. But there is no extensibility. There is no effective difference between storing the tile map (array of tile indexes) in a binary or text format. There won't be extensibility either way. The other parts of your format, though, those can be extensible.

Instead of storing a fixed list of fields (like a C struct), try handling things differently.

The tilemap format takes place in three parts. The first part is a null terminated string that contains an INI file. parse it using Allegro's set_config_data In that section, you can specify metadata fields… Maybe the level title, author, etc. Maybe the initial tile set to use. And you can always add more to it later, because it's extensible.

After that section, put another null terminated string that contains a Lua script. This script is effectively the main() function for that map: it loads and plays the music, fills the scene with objects, etc.

Finally include your binary or text—doesn't matter—blob of tile indexes.

The script should be created by the level editor. When the editor saves a level with an object in it, it actually adds a line to the script that creates the object and places it on the map at the target coordinates.

This is a good start, we've got a good text/binary file that is easy to parse and use because it's built on libraries (Allegro's INI routines and Lua). And, with the level editor, it's easy to create. In fact, you can open it up in a hex editor and edit the INI section or Lua section right there, and it will work, just fine. But we are still being too hard on ourselves. We can make this even easier to deal with.

(The next part of this post moves towards what Peter Wang suggested.)

Instead of having null terminated configuration, script, and tile map sections, let's split it into three files: level.ini, level.lua, and level.map. All of these are text files, and they live in a directory created just for them. The level editor's code is exactly the same, it's just the code to save the levels that's changed. The engine can load those files and use them identically as well.

What advantage does that give? Now we can edit any of the files in our individual editors, and it will have syntax highlighting and whatever other features the editors provide. We should never need to edit the files this way, because the level editor does it for us. Still, when we are debugging, it helps to have our normal repertoire available to use.

What disadvantage does this give us? Well, we've got a bunch of files laying around. It's ugly, and easy for files to accidentally move around, etc.

How do we rectify this? We zip the entire level directory. The zip file contains, in its root, level.ini, level.lua, and level.map. Now we only have one file again. We can rename it to something less obvious than ".zip" if we like. Plus, we still have the ability to use all of our tools to debug. Oh, and use the Allegro Zipfile Reader. You still have the extensibility of the separate files, plus the convenience of a single map file. And, when eveyrthing works properly, you don't even need to remember that the file is really a zip archive with a bunch of other files in it.

There's another layer of extensibility here. Take your level format and convert it into an archive format. The level now becomes level1 in the zip file, and every other entity gets its own directory. Use a VFS system to access them: LoadMap("path/to/archive.dat#level1"), just like Allegro's datafiles, but built on a standard format.

--
Tomasu: Every time you read this: hugging!

Ryan Patterson - <http://cgamesplay.com/>

23yrold3yrold
Member #1,134
March 2001
avatar

The main problem I have with all that is the heavy reliance on a million different libraries. I can't open my old Mapslapper files in anything but Allegro programs because I used packfiles with the 'p' set. :( I see where you're going and fair enough, maybe the zip option isn't hard to implement. I'll have to look into that option. I just don't want to make it a nightmare for random users trying to write code to open these files. :) I'm not sure how much I care about extensibility; again, these are tilemaps. ;D

Anyway, cookies are overdue, thanks for the input so far.

--
Software Development == Church Development
Step 1. Build it.
Step 2. Pray.

Evert
Member #794
November 2000
avatar

Quote:

The main problem I have with all that is the heavy reliance on a million different libraries. I can't open my old Mapslapper files in anything but Allegro programs because I used packfiles with the 'p' set.

That's why text files are good.
Yes, you can always write something that reads a binary file too, but then you'll always need to have a reference specification. If you ever lose that and need to work on your old data, you're screwed. A text file at least you might be able to decode with a simple text editor.

CGamesPlay
Member #2,559
July 2002
avatar

A dependence on libraries? Well, perhaps if you were making a library yourself, but do you really need a library just to handle tilemaps? I mean, these are tilemaps ;)

--
Tomasu: Every time you read this: hugging!

Ryan Patterson - <http://cgamesplay.com/>

Go to: