Портирование Gish на Android OS: использование библиотек OpenAL и GL4ES
В средних классах школы я любил прогуливать скучные гуманитарные предметы и вместо них проходить самые разные компьютерные игры. Но одному играть было чертовски скучно, поэтому я часто приходил в гости к своему другу. Мы покупали различные вкусности, собирались вместе в его комнате, включали компьютер и погружались в захватывающие игровые миры. Как-то раз, холодным зимним вечером, мой одноклассник показал мне забавную и интересную игру под названием Gish, которую он недавно скачал в Интернете. Это была достаточно своеобразная двумерная аркада, отличительной особенностью которой являлся необычный одноименный персонаж, представляющий собой небольшой жидкий шарик из чёрной смолы. К сожалению, сейчас я не помню, смогли мы тогда пройти эту замечательную игру до конца или нет (она была достаточно хардкорной), но её мрачный сеттинг, чёрный юмор, классная музыка и необыкновенные головоломки, связанные с физикой игрового мира, остались в моей памяти навсегда. В графическом плане Gish был достаточно простым, но благодаря оригинальной рисовке, интересным локациям и классной работе освещения, создавалось впечатление достаточно современной игры. Нам с другом было весело играть в Gish’а по очереди, проходя сложные уровни всё дальше и дальше. Таким образом, эта игра стала одной из моих любимых аркад для PC и отличным платформером для небольшой компании друзей.
Порт игры Gish, запущенный на Android-устройстве Motorola Photon Q.
История разработки инди-игры Gish берёт своё начало в 2003 году. Именно тогда независимая компания Chronic Logic, занимающаяся изданием и разработкой видеоигр, заключила контракт с художником и геймдизайнером Edmund’ом McMillen’ом, который впоследствии станет известным благодаря таким популярным инди-играм, как Super Meat Boy и The Binding of Isaac. Пока Edmund работал над графикой, программисты Alex Austin (под псевдонимом Cryptic Sea) и Josiah Pisciotta занимались написанием игрового движка. Разработка Gish была завершена весной 2004 года и уже в мае Chronic Logic выпустила игру на рынок США, где аркада получила восторженные и положительные отзывы критиков. Благодаря успеху игры, её дистрибуцией в 2004 году занялась такая компания, как Stardock, а в 2007 году Gish был добавлен в библиотеку игр в Steam’е. Кроме того, в 2010 году платформер был включен в первый сборник инди-игр под названием Humble Indie Bundle, который собрал более одного миллиона долларов. В знак признательности поддержавшему их сообществу, Cryptic Sea объявил о том, что исходный код игры Gish будет открыт и выпущен под лицензией GNU GPL v2.0, но ресурсы игры нужно будет приобретать отдельно.
Содержание:
1. Краткий обзор игры Gish
Как уже было сказано выше, главным героем игры является небольшой шарик смолы по имени Gish, который может изменять своё физическое состояние. Сюжет аркады не слишком замысловат и повествуется в нескольких статичных иллюстрациях перед началом первого уровня игры. Gish и его подружка Brea прогуливались в парке, как вдруг из канализационного люка вылезло мерзкое чудовище, которое утащило девушку под землю. Бесстрашный Gish прыгает за ним в канализацию и отправляется на поиски своей возлюбленной, после чего, собственно, и начинается сама игра, конечной целью которой является спасение несчастной Brea.
Повествование сюжета игры, скриншоты с Motorola Photon Q (превью, увеличение по клику).
Первый уровень платформера выполнен в виде обучающей локации, где игрока познакомят с основными клавишами управления и методами взаимодействия с игровым миром. Gish может становиться тяжёлым и твёрдым, чтобы давить своей массой врагов, ломать преграды и тонуть в воде. Для того, чтобы карабкаться по стенам и потолкам, наш герой может выдвигать специальные шипы на своей оболочке, которые, помимо этого, позволяют ему передвигать и тащить некоторые предметы. Ещё Gish умеет становиться скользким, что помогает ему протискиваться в различные узкие проходы и секретные места, часто встречающиеся на уровнях игры. Все эти умения можно комбинировать, что позволяет игроку с лёгкостью преодолевать некоторые трудные локации.
Обучающий уровень игры, Gish с помощью шипов карабкается по потолку, чтобы добыть янтарь, скриншот с Motorola Photon Q (превью, увеличение по клику).
Кнопка прыжка создаёт некоторый резонанс в теле Gish’а, комбинируя это действие с нажатием клавиш «вниз» и «вверх», можно высвобождать накопленную энергию и тогда главный герой будет довольно высоко подпрыгивать.
Локации платформера наводнены различными головоломками, связанными с физикой самой игры. В некоторых местах нужно найти и положить ящик на кнопку открывающую двери, чтобы пройти уровень дальше. Иногда потребуется подбрасывать камни вверх, чтобы пробить потолок и высвободить тяжёлый груз, который проломит пол и откроет проход в новые локации.
Одна из физических головоломок в игре, Gish приготовился подбросить камень вверх, чтобы пробить потолок и уронить тяжёлый груз вниз, скриншот с Motorola Photon Q (превью, увеличение по клику).
Уровни разбиты на пять различных глав, в каждой из которых локации выполнены в какой-либо определённой стилистике. Gish побывает не только в мрачной и грязной канализации, но и в затопленных шахтах, в подземном Аду, в древнем Египте и даже в заброшенной церкви.
Многообразие локаций в Gish, на последнем изображении первый босс в игре, скриншоты с Motorola Photon Q (превью, увеличение по клику).
В конце каждой главы игрок столкнётся с достаточно сложными боссами, после прохождения которых он попадёт на забавный переходный уровень, сочетающий в себе сеттинг сразу двух глав: предыдущей и последующей. Помимо этого, на таких уровнях можно получить дополнительные жизни и набрать множество очков.
Переходный уровень из Ада в древний Египет, сочетание сеттинга сразу двух глав, скриншот с Motorola Photon Q (превью, увеличение по клику).
Игра требует хорошей сноровки и к её управлению необходимо привыкать. Например, некоторые места проходить значительно легче, если у Gish’а был сохранён импульс разбега. Я довольно долго не мог научиться высоко прыгать, в игре есть некоторые места, где высокие прыжки необходимы для дальнейшего прохождения. Платформер Gish наполнен множеством секретов, скрытыми уровнями и различными пасхалками, что, несомненно, будет приятным сюрпризом для большинства игроков.
Секретный уровень в Gish, представляющий собой отсылку к игре Super Mario Bros., скриншот с Motorola Photon Q (превью, увеличение по клику).
Платформер от Cryptic Sea получился необыкновенной и оригинальной двумерной аркадой. Если вы никогда не играли в Gish, то обязательно ознакомьтесь с этой отличной игрой. В 2010 году я очень обрадовался тому, что исходники Gish стали доступными для изучения, поскольку всегда хотел поиграть в этот платформер на каком-нибудь смартфоне. Мобильная Java-версия игры, называемая Gish Reloaded и являющаяся сюжетным продолжением оригинала, была весьма обрезанной в плане графики и физики, а звуковое сопровождение и вовсе было куцым.
Порт мобильной Java-игры Gish Reloaded на Android OS, скриншоты с Motorola Photon Q (превью, увеличение по клику).
Играя в школьные годы в Gish Reloaded, я не ощущал ту мрачную атмосферу, которая присутствовала в компьютерной версии игры. Поэтому я захотел портировать Gish на свой MotoMAGX-смартфон, Motorola ZINE ZN5. Скачав исходный код, я понял, что из этой затеи абсолютно ничего не выйдет. Gish требовал OpenGL, а следовательно и GPU, который отсутствовал в моём телефоне. Программный рендеринг к такой игре написать было не в моих силах, поэтому я отложил эту идею до лучших времён и до более крутых смартфонов. Теперь я с уверенностью могу сказать, что эти времена наступили и я решил портировать компьютерную версию Gish на устройства под управлением Android OS.
2. Подготовка исходного кода Gish к портированию на Android OS
Как было отмечено выше, игра использует для рендеринга старую версию библиотеки OpenGL 1.3, которая недоступна на Android OS. Программист Pickle в 2013 году написал для Gish рендерер, использующий библиотеку OpenGL ES, чтобы перенести эту игру на портативные игровые консоли Pandora и GCW Zero. Он назвал свой проект GishGLES и любезно выложил его исходный код на GitHub. Я решил форкнуться от репозитория Pickle и воспользоваться его наработками по рендереру, поскольку OpenGL ES сейчас доступен на всех Android-устройствах.
Традиционно, я начал портирование движка игры со сборки из исходного кода рабочей версии Gish под GNU/Linux. Проекту требовались следующие библиотеки: SDL, OpenAL, Ogg Vorbis, PNG и OpenGL. Установив все необходимые зависимости, я сразу же столкнулся с проблемами при компиляции. Дело было в том, что Gish использовал старую версию библиотеки PNG, а в новой сломали API и мне пришлось немного переписать функцию loadtexturepng(), чтобы исправить все ошибки сборки. Позже я понял, что эта функция используется в недоделанной свободной реализации Freegish, а оригинальная игра работает только с текстурами в формате TGA. Поэтому на будущее я избавил Android-проект от зависимости в виде библиотеки поддержки текстур формата PNG.
Полную версию Gish’а я покупал ещё давно, в первом Humble Indie Bundle, поэтому я просто развернул Data-файлы платформера рядом со скомпилированным исполнительным бинарником и игра запустилась. Теперь, когда у меня была рабочая версия Gish, я взялся за её перенос на SDL2, так как эта библиотека официально доступна для Android OS. Каких-либо проблем с портированием движка на SDL2 у меня не возникло, этот процесс я описывать не буду, так как в статье про портирование игры Ken’s Labyrinth на Android OS я уже его подробно разбирал. Единственное затруднение возникло с получением списка видеорежимов, но обратившись к документации SDL2 и структуре SDL_DisplayMode, я полностью решил и эту проблему. Цикл, добавляющий видеорежимы в список доступных в настройках игры, получился следующий:
В библиотеке SDL2 на Android OS акселерометр умеет работать как джойстик, что довольно интересно и может быть полезным. Поэтому я решил оставить поддержку джойстиков в своём порте и вынести этот параметр в игровой лаунчер позже.
Подключенный джойстик Logitech F510 к телефону Motorola Moto X, спасибо за фотографию J()KER (превью, увеличение по клику).
Обычные джойстики, которые можно подключить к Android-устройствам, работают без особых проблем. Перенос платформера Gish на новую библиотеку SDL2 по времени занял у меня всего один вечер.
Теперь, когда игра работала через SDL2, мне требовалось найти порты остальных нативных библиотек, отсутствующих в стандартной поставке Android OS. Движок Gish использовал для вывода звука библиотеки Ogg Vorbis и OpenAL. Зависимость от первой либы разрешалась достаточно легко, я просто перенёс в проект внутренние куски кода из библиотеки SDL2_mixer, которые отвечали за поддержку звукового формата Ogg Vorbis. Здесь мне тоже пришлось столкнуться с некоторыми проблемами несовместимости API старых и новых библиотек. Gish использовал новый Ogg Vorbis, а куски из распотрошённого SDL2_mixer почему работали со старым, кроме того, названия заголовочных файлов немного отличались. Единственная проблема крылась в функции ov_read(), в новой версии библиотеки она была снабжена дополнительными параметрами. Раскидав все отличия по дефайнам и написав сценарий сборки статической библиотеки, я полностью исправил ошибки компиляции и продолжил своё исследование.
Далее оставалось дело за библиотекой OpenAL, а точнее, за её свободной реализацией под именем OpenAL Soft. Кроме официального репозитория, в котором была обеспечена поддержка Android OS, я нашёл в интернете несколько других портов этой либы: openal-soft-android, openal-soft/android и openal-soft/android/lowlatency. Собрав несколько тестовых приложений, я абсолютно не заметил какой-либо разницы между ними, и, поэтому, выбрал вариант openal-soft/android, так как эта библиотека получилась самой компактной и её исходный код располагался в официальных репозиториях проекта OpenAL Soft. Единственное, меня смутило то, что репозиторий не обновлялся с 2012 года. Зато там был необходимый мне файл Android.mk, являющийся сборочным рецептом либы. Современный OpenAL использовал CMake даже для сборки на Android OS и мне пришлось бы писать Android.mk самому по сборочному логу, что было весьма неблагородным делом. Тем не менее, старая библиотека отлично работала и мало весила, что меня полностью устраивало. Кроме того, я активировал в OpenAL поддержку вывода звука через OpenSL ES, что, как мне показалось, немного снизило нагрузку на CPU. Библиотека OpenSL ES сразу доступна в стандартной поставке Android NDK и используется практически на всех Android-девайсах для работы со звуком.
К слову, я немного изменил своё окружение для разработки Android-приложений. Если раньше я использовал дистрибутив Arch Linux, KDE Plasma 5, Eclipse и ant, то теперь я перешёл на Fedora 25, GNOME 3, Android Studio и Gradle. Потихоньку привыкаю к новой обстановке, которая кажется мне достаточно удобной для работы. Единственное, чтобы скрыть крупные и неказистые заголовки окон у развёрнутых программ, я установил специальное дополнение Pixel Saver, которое доступно на официальном сайте расширений GNOME 3.
Работа с кодом игры Gish в Android Studio, скриншот из окружения GNOME 3 (превью, увеличение по клику).
Компания Google в последнем обновлении Android SDK полностью сломала Android ADT и возможность создания приложений в Eclipse, поэтому мне пришлось переводить все свои предыдущие проекты на Android Studio. К сожалению, в Android Studio всё ещё достаточно слабая поддержка Android NDK, C, C++ и CMake, поэтому в качестве второй среды разработки у меня был постоянно запущен Qt Creator, в котором я вносил изменения в нативный код движка игры Gish.
Запуск нативной сборки Gish в GNU/Linux, скриншот из окружения GNOME 3, на фоне интегрированная среда разработки Qt Creator (превью, увеличение по клику).
Возможно, в будущем я полностью перейду на Android Studio, но пока мне нравится скорость работы Qt Creator и качество разбора кода парсером Clang.
Итак, на следующий день после начала работы над кодом, я смог собрать рабочий APK-пакет, который запускал игру Gish на моём Android-устройстве Motorola Photon Q. Конечно, я столкнулся с большой кучей проблем, которые позже постарался решить наиболее оптимальными способами. Но сам факт того, что игра заработала на моём смартфоне без значительных изменений, меня настолько обрадовал, что я забросил все дела и начал проходить эту игру на девайсе, используя физическую клавиатуру. Мне даже удалось полностью пройти две главы, чему я несказанно удивился.
3. Решение возникших проблем порта игры Gish на Android OS
Запустив игру на Android-смартфоне, я заметил, что в ней полностью отсутствовали звуковые эффекты, но при этом музыка работала без проблем. Внимательно изучив исходный код Gish, я увидел, что звуки в формате WAV и DAT загружаются с помощью библиотеки SDL2, посредством макроса SDL_LoadWAV(), но при этом SDL2 никак не участвует в их проигрывании, этим занимается OpenAL. Кроме того, я обнаружил, что в исходном коде очень часто используется функция chdir() для изменения директории с нужными Data-файлами игры. Отладка помогла мне выявить проблему отсутствия звука. Оказывается, этот макрос в Android-версии SDL2 не дружит с относительными путями, а только с абсолютными. Возможно, это как-то связанно с поддержкой assets’ов в функциях подмножества SDL_RWops. Мне пришлось написать небольшую функцию stringconcat(), конкатенирующую строки и передавать в макрос полный путь к звуковым файлам: