среда, 9 апреля 2014 г.

Записки программиста #10. Портирование на телефон.

Игра изначально разрабатывалась под целевые платформы Windows Phone и Windows 8, с учетом возможного портирование на другие платформы, для этих целей я выбрал monogame. Для простоты и для удобства, игра изначально писалась под десктоп, с использованием SDL.
Когда игра была уже почти написана и настроен примерный баланс, пришло время заняться переносом на Windows Phone. Изначально, я хотел выпустить игру на Windows Phone 7 и Windows Phone 8, но шаблон в VS Windows Phone 7 SL+XNA не хочет загружаться, да и все текстурные атласа следует перепаковать под 800*480, а доля Windows Phone 7 постоянно падает и лень победила – игра выйдет только под Windows Phone 8 +, пора менять свою старенькую Lumia 800…

Игра разбита на движок и на саму игровую логику. Для переноса был создан новый проект Windows Phone. В который был перенесен код в качестве ссылки. В некоторых местах пришлось написать #if WINDOWS … #elif WP8  …  #endif, но в целом таких мест было мало, тк заранее предполагалась полное портирование на другие платформы. Но неприятности подстерегали меня сразу после запуска.

Проблемы при портировании

Нету поддержки ориентации пейзаж при использовании DrawingSurfaceBackgroundGrid, а именно он находит в шаблоне по умолчанию. Можно использовать DrawingSurface, но он менее производительный.
Собственно, вопрос не новый и освещается он в теме.
Суть сводится к одному – используйте DrawingSurface и не заморачивайтесь, что собственно и было изменено в шаблоне по умолчанию.

Все остальное заработало быстро, что меня порадовало довольно сильно. Также пришлось дописать локику для Touch, ну это понятно и не потребовало довольно больших временных вложений.
Но после небольшого тестирования стало ясно, что не все так хорошо, проседает производительность притом сильно, а также память, которая кушалась быстро и много.
Для разнообразия и ощущения всех проблем я решил прогнать его на всех доступных мне телефонах: Lumia 520, Lumia 920, Lumia 1520, HTC 8X.
Изначальное разрешение для движка и всего мира я взял 1280*768, его предполагалось масштабировать по оси X и по оси Y, но по оси Y убирать излишки если это необходимо (это в районе 40 px сверху и снизу). Все полетело не сразу и пришлось немного поработать напильником, но результат меня порадовал.

И так на повестке дня две большие проблемы: память и производительность.
Я решил начать с памяти. Первая большая утечка была при переходе с одного экрана на другой и обратно, память не уменьшалась, не чистил за собой RenderTarget2D. При переходе между экранами используются RenderTarget2D, для уменьшение его размера я использовал DepthFormat.None, тк мне не нужен буфер глубины.
Эти нововведения позволили добиться 146 Мб в пике из 150 Мб - максимально доступных для WP8 телефонов с маленьким количеством памяти, как например Lumia 520.
Но к сожалению, не всегда получается очищать память вовремя и запас в 4Мб совсем не радовал. Я решил перепаковать свои текстуры более плотно. Изначально все текстурные атласы разделялись логически: для интерфейса, для конкретной карты, для всех карт. Собственно, я объединил атласы для интерфейса и для всех карт. Это потребовало очень много ручного труда, но зато в запасе сейчас 10-20Мб свободного места в пике.

Следующий, не менее важный вопрос – это производительность. Расставив временные метки стало ясно, что больше всего времени выполняется обновление частиц, которые я использовал для дыма и обновление физического мира.
С частицами все сразу стало ясно, для телефона их многовато, тысяча активных частиц, а также много модификаторов для отдельной частицы. Я решил ограничится десятками активных частиц и убрать лишние модификаторы, выглядит не так красиво, но в целом приемлемо.
А вот с физикой пришлось повозиться не мало. Был очень странный сценарий воспроизведения проблемы: загружаем камни, все ок, едем медленно все ок, едем быстро FPS проседает в ноль. Для физики я использую, как и говорил раньше, Farseer Physics Engine. Настройки у него обширные, на просторах интернета нашел рекомендации изменить:

  • VelocityIterations - число итераций скорости, используемых в решателe
  • PositionIterations - число итераций положение, используемых в решателе
  • ContinuonsPhysics - включение / выключение непрерывного обнаружения столкновений (CCD)
Они влияют на производительность, но к сожалению, не так критично, как мне хотелось бы.
После долгих мучений с настройками, которые не дали желаемого результата, решил попробовать иначе. Камни я строил на основе текстуры камней, в итоге имел массив вертексов, я решил серьезно упросить геометрию и это дало необходимый результат.

Загрузка ресурсов

До момента портирования игры на телефон, я с загрузкой ресурсов не заморачивался, поднимал все и сразу. На телефоне этот вопрос встал острее, я решил не откладывая данный вопрос в долгий ящик и взяться за него. Поскольку подгружать все даже в фоне на старте не правильно, я решил разбить загрузку на несколько этапов:
  • Старт приложения
  • Загрузка GUI
  • Загрузка игрового уровня
  • Загрузку GUI от уровня я разнес специально, тк карт и машины не мало и подгружать все сразу смысла нету.

При старте приложения, в основном потоке, подгружаются необходимый минимум, в моем случае это первый атлас интерфейсов и шрифт, настройки.
После чего выводиться заставка и подгружаются остальные в фоне. Анимированную заставку делать не стал, тк загрузка происходит довольно быстро.
При нажатии играть, выводиться заставка загрузки, в фоне подгружаются текстурные атласы для карт и другая сопутствующая информация для игры, после загрузки, стартует вторая фаза – формирования уровня.  После чего из экрана загрузки переходим на сам игровой уровень.
Для большей наглядности схема загрузки:



Аудио в игре тоже не забыто. Фоновая музыка занимает не самое последнее место в игре, но о её размере говорить излишне, он далеко не маленький. В игре присутствует два фоновых трека: для меню и для самой игры. Для уменьшения размера, каждый трек разбит на три части, выглядит это так: интро, припев, куплет, припев, куплет, припев, после чего трек повторяется. Как видим если все части будут равны, в данном сценарии мы экономим 50%, а это не мало.

В завершении статьи, я хочу пригласить всех желающих, обладающих телефонами Window Phone 8 принять участие в бета тестировании!

Для участие в тесте, необходимо прислать письмо на dampirik@rambler.ru с пометкой «Beta test TruckingMania», в письме необходимо указать Ваш LiveID, Имя (ник), информацию о мобильном устройстве. После чего Вам будет выслана ссылка для тестирования.