Personalmente, soy más fanático de los formatos binarios con secciones (como Windows PE, pero mucho más simple). También son más fáciles de analizar (pero esa es solo mi opinión ... Trabajé con XML lo suficiente como para darme dolores de cabeza, comprobando si getElementByName ha devuelto un solo valor o una lista de valores ... ugh). Entonces, si yo fuera tú, lo haría algo como esto:
".MMF\0" // magic value at the start, null-terminated string. stands for My Map Format :)
char header_length // useful when parsing. char is a byte, of course, an unsigned one
char version // version of the map file. (you don't really need ints here, because you probably won't be needing more than 255 versions for example, but you can also use them)
char* map_name // null terminated string describing the name of the level/map
char* author_name // if you are going to have a map editor for the general public, it would be nice to credit the person who made the map
int width // it's probably wise to plan ahead and expect an int here when you're parsing the file
int height
".layer\0" // we begin another subsection
char header_length
char type // type of the layer. for example, you can put 1 there if you want this to be a layer describing different tiles/block in a Terraria like game
".data\0" // yet another subsection. this will hold the data for the tiles
// in a hypothetical terraria 2d game, you would lay down tiles from
// the top-right corner (0,0) and then begin writing row after row
// write(1,0); write(2,0); write(3,0); ... then write(0,1); write(1,1);
// write(2,1); write(3,1); and so on..
char t1 // tile at (0,0). for example, value 0 is empty, or passable tile
char t2 // tile at (1,0). this might be a dirt block - value 1
char t3 // tile at (2,0). a rock, perhaps? value 3
(...)
char tn // tile at (width-1, height-1) or the bottom-left tile
".layer\0" // another layer.
char header_length
char type // let this on be of value 2, and let it describe portals.
// putting portals in a game makes it instantly 20% cooler
".data\0"
char t1 // 0, no portal here at tile (0,0)
char t2 // still nothing
char t3 // nope, try again
(...)
char t47 // at some location, you made a red portal. let's put 1 here so we can read it in our engine
(...)
char t86 // looke here, another 1! you can exit here from location corresponding to t47
(...)
char t99 // value 2. hm, a green portal?
(...)
char tn // bottom-left tile, at (width-1, height-1)
".layer\0" // another layer
char header_length
char type // value 3, player&enemies spawn points
char something // you don't have to have header len fixed. you can add stuff later
// and because you were smart enough to put header length
// older versions can know where the stuff of interest lays
// i.e. version one of the parser can read only the type of layer
// in version two, you add more meta-data and the old parser
// just skips it, and goes straight to the .data section
".data\0"
char t1 // zero
char t2 // zero
char t3 // zero
(...)
char t42 // a 1 - maybe the player spawn point. 5 tiles to the right
// there's a red portal
(...)
char t77 // a 2: some enemy spawn point
(...)
char tn // last tile
,
Ventajas:
- Se ve bien.
- Te hace pensar que sabes algo sobre programación, hacer cosas a la antigua usanza.
- Puede escribir manualmente sus niveles en un editor hexadecimal:
- Generalmente más rápido que INI y XML, tanto desde la perspectiva de escritura como de lectura
- Es una larga secuencia de datos de bytes, en realidad. No es necesario dedicar tiempo a hacer que se vea bonita, con sangría (como lo que le gustaría hacer con XML).
- Es fácil agregar cosas en los encabezados. Si una parte de los datos aparece en la parte inferior del encabezado, se puede indicar a las versiones antiguas de analizadores que eviten y salten a la parte del archivo que entienden.
Desventajas
- Debe cuidar bien la ubicación de los datos.
- Los campos de datos deben ser ordenados.
- Debes saber su tipo en el analizador, como dije, es solo una larga secuencia de bytes.
- Mover datos por una ubicación (por ejemplo, se olvida de escribir el tipo de capa; el analizador espera un byte allí y encuentra el valor de '.' - eso no es bueno) desordena toda la matriz de datos desde ese punto en adelante.
- Es más difícil saltar directamente: no hay API, no hay función como getLayerWidth (), tiene que implementar todo eso usted mismo.
- Potencialmente hay mucho espacio desperdiciado. Tome la tercera capa, por ejemplo. Ciertamente estará lleno de ceros. Sin embargo, esto puede evitarse si usa algún tipo de compresión. Pero una vez más, eso está jugando con cosas de bajo nivel una vez más ...
Pero lo mejor de este enfoque en mi opinión es: puedes hacerlo todo por ti mismo. Muchas pruebas y errores, pero al final, terminas aprendiendo mucho.