Лично я больше поклонник бинарных форматов с разделами (например, Windows PE, просто намного проще). Их также легче анализировать (но это только мое мнение .... Я работал с XML достаточно, чтобы вызывать головную боль, проверяя, вернул ли getElementByName одно значение или список значений ... тьфу). Итак, на вашем месте я бы сделал это примерно так:
".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
,
Преимущества:
- Выглядит круто.
- Заставляет вас думать, что вы что-то знаете о программировании, делах по старинке
- Вы можете вручную написать свои уровни в шестнадцатеричном редакторе:
- Как правило, быстрее, чем INI и XML, с точки зрения написания и чтения
- На самом деле это длинный поток байтовых данных. Не нужно тратить время на то, чтобы сделать его красивым, с отступами (например, то, что вы хотели бы сделать с XML).
- В заголовки легко добавлять вещи. Если часть данных находится в нижней части заголовка, старые версии анализаторов могут быть проинструктированы, чтобы избежать этого и перейти к той части файла, которую они понимают.
Недостатки:
- Вы должны позаботиться о размещении данных.
- Поля данных должны быть упорядочены.
- Вы должны знать их тип в парсере - как я уже сказал, это просто длинный поток байтов.
- Перемещение данных на одно место (например, вы забыли записать тип слоя; анализатор ожидает там байт и находит значение «.» - это нехорошо) испортил весь массив данных с этого момента.
- Труднее прыгнуть прямо - нет API, нет функции, подобной getLayerWidth () - вы должны реализовать все это самостоятельно.
- Там потенциально много пустого места. Возьмите третий слой, например. Он, безусловно, будет заполнен множеством нулей. Это может быть обойдено, если вы используете какое-то сжатие. Но, опять же, это опять мешает вещам низкого уровня ...
Но самое лучшее в этом подходе, на мой взгляд, - это сделать все самостоятельно. Много проб и ошибок, но в конце вы многому научитесь.