
Java Properties vs XML
Разрабатывая код продукта самостоятельно постоянно сталкиваешься с интересными вещами, на которые в другой ситуации не обратил бы внимания.
В этой заметке речь пойдёт о формате конфигурационного файла.
До игр я занимался разработкой на Java, поэтому когда возникла необходимость вынести дизайнеру все необходимые параметры в отдельный файл, особо не думая, взял структуру Java properties за основу.
Данные стали выглядеть вот так.
В принципе, нормально, есть некоторая избыточность в виде номера монстра в каждой строке, но ничего страшного.
Парсилась подобная структура примерно вот так.
Где getProperty пробегался по всему файлу ища параметр по ключу.
И так оно прекрасно работало во флеш версии.
Затем началось портирование игры на мобильные устройства, но ближе к завершению решили её не выпускать, а сделать на её основе что-то другое.
Со временем я начал замечать что после загрузки ресурсов есть какое-то неприятное подвисание на несколько секунд, которое в процессе разработки только увеличивалось.
Проблема оказалась в парсинге конфигурационного файла, т.к. он значительно вырос со времён первой игры да ещё и его обработка стала происходить на мобильном устройстве.
На третьем айпаде парсинг стал занимать 5800 мс.
На компьютере — 1800 мс.
Надо было что-то делать.
Простым парсером на Java я преобразовал конфигурационный файл в XML, допилил его ручками, затем адаптировал внутриигровой парсер к новому виду данных.
В итоге получилось следующее.
Избыточность, в виде номера монстра, ушла в прошлое, ну а парсинг стал таким.
Результат превзошёл мои ожидания.
На третьем айпаде парсинг стал занимать 270 мс, т.е. код стал работать в 21 раз быстрее.
На компьютере разница оказалась ещё более значимой — 50 мс, т.е. код стал в 36 раз быстрее.
К слову, на текущий момент, конфигурационным файл — это XML в 2779 строк.
До этого, в txt, он занимал 2377 строк.
В завершении хотелось бы спросить дорогих читателей — нужны ли подобные заметки, интересно ли про такое читать?
В этой заметке речь пойдёт о формате конфигурационного файла.
До игр я занимался разработкой на Java, поэтому когда возникла необходимость вынести дизайнеру все необходимые параметры в отдельный файл, особо не думая, взял структуру Java properties за основу.
Данные стали выглядеть вот так.
#goblin
mob8.id=08
mob8.armour=light
mob8.speed=3.5
mob8.flying=true
mob8.fps=30
mob8.hpMod=1.01
В принципе, нормально, есть некоторая избыточность в виде номера монстра в каждой строке, но ничего страшного.
Парсилась подобная структура примерно вот так.
private function parseMobs() : void
{
mobs = new Vector.<MobTemplate>();
var i : int = 0;
while (true)
{
var key : String = KEY_MOB + i;
var id : String = getProperty(key + PARAMETER_ID);
if (isEmpty(id))
{
break;
}
var mob : MobTemplate = new MobTemplate(id);
mobs.push(mob);
i++;
}
}
Где getProperty пробегался по всему файлу ища параметр по ключу.
private function getProperty(key : String) : String
{
for each (var str : String in strings)
{
if (str.indexOf(key) == 0)
{
return str.replace(key + '=', '');
}
}
return null;
}
И так оно прекрасно работало во флеш версии.
Затем началось портирование игры на мобильные устройства, но ближе к завершению решили её не выпускать, а сделать на её основе что-то другое.
Со временем я начал замечать что после загрузки ресурсов есть какое-то неприятное подвисание на несколько секунд, которое в процессе разработки только увеличивалось.
Проблема оказалась в парсинге конфигурационного файла, т.к. он значительно вырос со времён первой игры да ещё и его обработка стала происходить на мобильном устройстве.
На третьем айпаде парсинг стал занимать 5800 мс.
На компьютере — 1800 мс.
Надо было что-то делать.
Простым парсером на Java я преобразовал конфигурационный файл в XML, допилил его ручками, затем адаптировал внутриигровой парсер к новому виду данных.
В итоге получилось следующее.
<!-- goblin -->
<mob id="8">
<armour value="light" />
<speed value="3.5" />
<flying value="true" />
<fps value="30" />
<hpMod value="1.01" />
</mob>
Избыточность, в виде номера монстра, ушла в прошлое, ну а парсинг стал таким.
private function parseMob() : void
{
mobs = new Vector.<MobTemplate>();
var list : XMLList = Resources.getConfig().child(MOBS);
for each (var xml : XML in list.children())
{
var id : String = xml.attribute(ID);
var mob : MobTemplate = new MobTemplate(id);
mobs.push(mob);
}
}
Результат превзошёл мои ожидания.
На третьем айпаде парсинг стал занимать 270 мс, т.е. код стал работать в 21 раз быстрее.
На компьютере разница оказалась ещё более значимой — 50 мс, т.е. код стал в 36 раз быстрее.
К слову, на текущий момент, конфигурационным файл — это XML в 2779 строк.
До этого, в txt, он занимал 2377 строк.
В завершении хотелось бы спросить дорогих читателей — нужны ли подобные заметки, интересно ли про такое читать?
- +7
- Knight
Комментарии (21)
И загружаешь в проект этот бинарник (можно из файла).
Потом просто:
Плюс это некая защита от игроков, которые меняют конфиги для упрощения игры. Просто сейчас ты упрощаешь жизнь себе и тем самым усложняешь игроку :)
По сути, сейчас у геймдизайнера есть игра с внешним конфигом, он его меняет и живёт счастливо, зачем ему выполнять лишнюю операцию при каждом чихе созданию бинарника?
Другое дело перегнать все ресурсы в бинарники перед публикацией игры, это да.
чтобы потом знать как вручную распарсить массив байтов где-нибудь на сервере?
Вообще некоторые сервера имеют встроенную поддержку парсинга AMF. Так же в сети много либ на любой вкус и цвет.
Если надо максимально сжать — можно использовать последний AFM3 формат.
Создаем некий файл .json, правим, в релиз сборке вместо загрузки json, копипастим в as3 файл и объект с параметрами берем из него.
пример json:
Создаем as3 файл, например GoblinConfig.as3 создаем единственную статическую константу в нем, это и будет конфиг:
Сюда естественно можно добавить и метод возвращающий конкретные настройки по id.
Перегнал xml в json — получилось 3028 строк плюс необходимость ручками красоту навести.
Кроме того, поддержка xml в Eclipse гораздо лучше и удобней, чем json, да ещё у меня Flash Builder практически сразу упал, после открытия конфига в json.
Так что пока оставлю xml, но json буду иметь в виду, спасибо!
Из-за того, что изначально конфиг был маленьким, то время парсинга в глаза не бросалось.
Увеличение скорости в 20-30 раз произошло, как я понимаю, из-за того, что xml парсится по уровням, т.е. на верхнем уровне, чтобы получить необходимый раздел, нужно сделать не до 2300 проверок, а всего до 11.