Archived

This topic is now archived and is closed to further replies.

Moogle

Map File Format

Recommended Posts

I just started experimented with tile based games and I am writing a level editor. Right now I am just using a 2d array of integers to store the id of all the tiles. That works great, but how do I store entitites like teleports to other maps (doors), enemies and other NPCs ?

Share this post


Link to post
Share on other sites
There are two schools of thought on this:

1) Make the entities tiles themselves. Upside: easiest to implement. Downside: moving entities have issues as far as what is underneath them...nothing.

For example, teleporters. If you are using int''s (32-bits), use the low 16 bits for your item/tile ID, and use the high 16 bits for an X/Y destination.

2) Have a seperate data structure for entities. Upside: more flexible, can extend easily. Downside: added layer of complexity.

For example, create a linked list of entities. Every time you or another entity moves, check the positions of all of the entities in the linked list.

How would I store them? Personal preference: store the map in one file, entities in another, or use a PAK-style file format and combine them that way. I come from a testing background, and I''ve seen too many instances where when too much stuff was combined into a single file, and a change to one area had wide-ranging effects on others.

RomSteady - Able to leap off tall buildings in a single bound

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
You could have an identifier (byte) for each special type you want to safe

  
enum Specials { ID_TELEPORT, ID_ENEMY, ID_NPC, NO_MORE_SPECIALS };

class Teleport {
//...

char getType() const {
return ID_TELEPORT;
}
}

class Npc {
//...

char getType() const {
return ID_NPC;
}
}

Then when you want to write the objects, just use something like


  template<typename T>
void writeObject(const T& object) {
writeByte(object.getType());
writeInt(sizeof(object));
//writes all bytes from the object, one by one

writeAll(&object, sizeof(object));
}

//somewhere else:

{
Teleport teleport1;
Npc myNpc;
writeObject(teleport1);
writeObject(myNpc);
//use a loop to write all the stuff from the editor :D

writeByte(NO_MORE_SPECIALS);
}


And when you want to read them:


  
while(true) {
char identifier = readByte();
if (identifier == NO_MORE_SPECIALS) break;

int sizeOfNewObject = readInt();
void* memoryForNewObject = reinterpret_cast<void*>(new char[sizeOfNewObject]);

//reads sizeOfNewObject amount of bytes one by one and stores them to memoryForNewObject

readAll(memoryForNewObject, sizeOfNewObject);

switch (identifier) {
case ID_TELEPORT:
addTeleport(reinterpret_cast<Teleport*>(memoryForNewObject));
break;
case ID_NPC:
addNPC(reinterpret_cast<Npc*>(memoryForNewObject));
break;
}
}

I have NO idea if it works and it''s probably not a very good way to save objects.. At least it looks pretty ugly. But I just felt the urge to write something :D

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Oh yah, I forgot to mention... If you want a safer method which needs more writing, try this:

  
class Teleport {
//...

void writeMe() {
writeByte(ID_TELEPORT);
writeInt(x); //x, y coordinates and so on

writeInt(y);
}

void readMe() {
readInt(x);
readInt(y);
}
}

//somewhere else

{
teleport.writeMe();
writeByte(NO_MORE_SPECIALS);
}

And to read

  
while(true) {
char identifier = readByte();
if (identifier == NO_MORE_SPECIALS) break;

switch (identifier) {
case ID_TELEPORT:
Teleport* teleport = new Teleport();
teleport->readMe();
addTeleport(teleport);
break;
case ID_NPC:
Npc* npc = new Npc();
npc->readMe();
addNpc(npc);
break;
}
}

That way you need to write writeMe() and readMe() functions for all object types.. But if your objects contain pointers, then you must do it this way.

Share this post


Link to post
Share on other sites