Портирование Ken’s Labyrinth на Android OS с помощью библиотеки SDL 2.0

Игра Ken’s Labyrinth была разработана Ken’ом Silverman’ом и выпущена компанией Epic MegaGames в далёком 1993 году. Ken Silverman в первую очередь известен как американский программист, создавший игровой движок Build Engine для компании 3D Realms, на нём впоследствии будут выпущены такие известные игры, как Duke Nukem 3D, Blood и Shadow Warrior. Движок, используемый в Ken’s Labyrinth, является неким прародителем Build Engine, в техническом плане он сопоставим с движком Wolfenstein 3D от id Software, но имеет несколько интересных преимуществ, например, интерактивные спрайты и текстуры, благодаря которым в игре реализованы карты уровней и специальные игровые автоматы, известные как слот-машины «однорукий бандит». Спустя несколько лет после выхода игры, когда её продажи практически прекратились, Ken Silverman выложил наиболее полный дистрибутив Ken’s Labyrinth на свой сайт и игра стала доступна для свободной загрузки. Немного позднее был опубликован и её исходный код.

После открытия исходного кода Jan Lönnberg портировал игру на современные операционные системы, используя библиотеку OpenGL для вывода графики, библиотеку SDL для обработки событий ввода, а также для вывода звука и эмулятор AdLib, написанный тоже Ken’ом Silverman’ом, для воспроизведения игровой музыки. Так родился проект LAB3D/SDL, предоставляющий возможность запустить Ken’s Labyrinth на любых операционных системах, на которых доступны библиотеки OpenGL и SDL. Позже Jared Stafford, использующий никнейм jspenguin, внёс некоторые улучшения в проект LAB3D/SDL, добавив способ загрузки PNG-текстур высокого разрешения, метод рендеринга теней и световых бликов в корректной перспективе, правильную скорость анимации и множество других исправлений. В 2010 году разработчик Scott Smith, использующий никнейм Pickle, переписал рендеринг LAB3D/SDL с OpenGL на OpenGL ES, что позволило запускать Ken’s Labyrinth на различных портативных игровых устройствах, таких как GP2X Caanoo или Pandora.



Порт игры Ken’s Labyrinth, запущенный на Android-устройстве Motorola Droid 4.

Впервые в Ken’s Labyrinth я поиграл в 2010 году на портативной консоли GP2X Caanoo, имеющейся у моего друга. Меня сильно привлекают подобные старые игры, поэтому я решил портировать Ken’s Labyrinth и на своё мобильное устройство: Motorola ZN5 на платформе MotoMAGX. Увы, но этот смартфон не имел графического 3D-ускорителя с поддержкой OpenGL ES, а потому портирование без переписывания значительной части движка, отвечающей за вывод графики, было бы весьма затруднительным. Время шло, у меня появлялись новые интересные гаджеты на Android OS и вот, спустя пять лет, я вспомнил про ту неудачную попытку портирования игры и решил её повторить, но уже для современных смартфонов, которых у меня на момент написания статьи несколько: Motorola Droid 4 и Motorola Photon Q. Эти устройства на Android OS имеют на борту графические 3D-ускорители, обладающие достаточной производительностью и функциональностью для подобного рода игр.

За основу будущего проекта я решил взять исходные коды порта LAB3D/SDL, модифицированные jspenguin’ом и применить к ним патчи для поддержки OpenGL ES от Pickle: таким образом задействуются возможности OpenGL ES версии 1.0, что благоприятно отразится на списке поддерживаемых Android-устройств. Как и в оригинале, на компьютере LAB3D/SDL при своём первом запуске отображает специальный конфигуратор, где можно настроить различные опции и параметры, а после выхода из него и по повторному запуску исполнительного файла уже запускается сама игра. Я бы хотел сохранить подобное поведение приложения и в Android-версии порта.

Содержание:

1. Портирование с SDL 1.2 на SDL 2.0
2. Портирование с OpenGL на OpenGL ES: решение проблем
3. Интересная проблема с отображением некоторых PNG-текстур
4. Освобождение от библиотеки SDL2_image
5. Дополнительные возможности для Android OS в SDL 2.0
6. Java-обёртка и лаунчер
7. Реализация сенсорного управления
8. Заключение, полезные ссылки и ресурсы

1. Портирование с SDL 1.2 на SDL 2.0

Сначала я решил полностью отказаться от использования библиотеки SDL, но посмотрев код, я увидел, что она весьма активно используется движком для потоков, звука и для самой графики. Мне пришлось её оставить, но с небольшими оговорками. LAB3D/SDL использует старую SDL версии 1.2, которая официально не имеет поддержки Android OS, а её реализации от энтузиастов не отличаются приемлемым качеством работы. В новой ветке SDL версии 2.0 появилась официальная поддержка как Android OS, так и iOS, но увы, API библиотеки несовместим с версиями прошлой ветки, поэтому код будет требовать внесения изменений, хотя и весьма незначительных. Мной было решено сначала портировать LAB3D/SDL на SDL 2.0, а потом уже проверить возможность работы игры под Android OS.

Разработчиками SDL 2.0 был написан специальный документ: SDL 1.2 to 2.0 Migration Guide, следуя предписаниям которого можно без особых трудностей перенести на SDL 2.0 любое SDL-приложение. Вкратце, суть сводится к следующему:

  1. Вместо SDL_SetVideoMode() следует использовать SDL_CreateWindow() и SDL_CreateRenderer();
  2. Вместо SDL_ListModes() следует использовать SDL_GetDisplayMode() и SDL_GetNumDisplayModes();
  3. Вместо SDL_UpdateRect() и SDL_Flip() следует использовать SDL_RenderPresent();
  4. В дополнение к SDL_Surface можно использовать SDL_Texture;
  5. Вместо SDL_VideoInfo() следует использовать SDL_GetRendererInfo() и SDL_GetRenderDriverInfo();
  6. Вместо SDL_GetCurrentVideoDisplay() следует использовать SDL_GetWindowDisplayIndex();
  7. Эквивалент события SDL_VIDEORESIZE теперь SDL_WINDOWEVENT_RESIZED;
  8. Вместо SDL_GL_SwapBuffers() следует использовать SDL_GL_SwapWindow().

Кроме того, необходимо проверить способ обработки нажатия клавиш на клавиатуре, так как в SDL 2.0 поддержка Unicode была реализована без костылей вроде функции SDL_EnableUNICODE(), которую нужно было вызывать, когда необходимо было получить символ, отличный от ASCII.

Трудности переноса LAB3D/SDL на SDL 2.0 у меня возникли лишь в обработчике событий клавиатуры, поскольку там использовались разные методы взаимодействия с ней. Пришлось писать небольшие вспомогательные функции-обёртки, которые я выделил в отдельные файлы sdl2keyhelper.h и sdl2keyhelper.c:

Функция getOldAsciiKeyCode() принимает новый код клавиши, используемый в SDL 2.0, и возвращает старый, который использовался в прошлой SDL-библиотеке. Кроме того, в SDL версии 2.0.3 никак не обрабатывались события нажатий кнопок D-Pad’а, поэтому мне пришлось написать и использовать функцию patchAndroidKeysDpadSDL2():

К счастью, буквально спустя два дня после начала работы над проектом, библиотека SDL обновилась до версии 2.0.4 и D-Pad заработал без подобных ухищрений и надобность в этой функции отпала.

Таким образом, LAB3D/SDL перестал зависеть от старой SDL-библиотеки и перебрался на современную SDL 2.0, что хорошо поспособствует портированию игры на Android OS. Немного позже я узнал, что jspenguin совсем недавно уже портировал движок на SDL 2.0 и выложил наработки в свой публичный репозиторий, так что этот шаг можно было пропустить, так как я проделал аналогичную работу. Мне лишь нужно было взять исходники более новой версии.

<< Перейти к содержанию

2. Портирование с OpenGL на OpenGL ES: решение проблем

Устройства, работающие на Android OS, как и многие другие портативные гаджеты, имеют поддержку OpenGL ES, но не имеют поддержки обычного «компьютерного» OpenGL. Для реализации последнего используется специальная сторонняя библиотека, NanoGL, написанная программистом Olli Hinkka. Мне не хотелось тянуть дополнительные зависимости в проект и я с удовольствием воспользовался наработками Pickle, который после портирования LAB3D/SDL на GP2X Caanoo и Pandora поделился с сообществом своими OpenGL ES-патчами. Казалось бы: бери их, применяй и будет всё отлично, но не тут-то было!

После тестовой сборки игра отлично запустилась и заработала на моём Droid 4, но на Photon Q, при выходе в главное меню игры, я увидел следующее:



Битое искажённое изображение, скриншот с Motorola Photon Q (превью, увеличение по клику).

Изображение сильно билось, искажалось, но восстанавливалось после выхода из главного меню. На поиск причины такого поведения я потратил почти целый день. Оказывается, что этот баг присутствует только в устройствах, которые используют графический ускоритель Adreno, на PowerVR, который, к слову, используется в Pandora и Droid 4, всё работает отлично. Дело было в том, что LAB3D/SDL для отрисовки изображения использует технологию «грязных прямоугольников», когда прорисовывается не весь кадр целиком, а лишь необходимая прямоугольная область, а то что находится за областью отрисовки, остаётся с предыдущего кадра. Это сделано в целях экономии производительности, но некоторые графические ускорители, в числе которых и находится Adreno, не гарантируют, что при вызове функции обновления экрана, за областью обновления останется буфер из предыдущего кадра. Документация SDL 2.0 по этому поводу тоже предупреждает:

================================================================================
A note regarding the use of the «dirty rectangles» rendering technique
================================================================================
If your app uses a variation of the «dirty rectangles» rendering technique, where you only update a portion of the screen on each frame, you may notice a variety of visual glitches on Android, that are not present on other platforms. This is caused by SDL’s use of EGL as the support system to handle OpenGL ES/ES2 contexts, in particular the use of the eglSwapBuffers function. As stated in the documentation for the function «The contents of ancillary buffers are always undefined after calling eglSwapBuffers». Setting the EGL_SWAP_BEHAVIOR attribute of the surface to EGL_BUFFER_PRESERVED is not possible for SDL as it requires EGL 1.4, available only on the API level 17+, so the only workaround available on this platform is to redraw the entire screen each frame.
Reference: http://www.khronos.org/registry/egl/specs/EGLTechNote0001.html

Кстати, на stackoverflow.com и gamedev.stackexchange.com обсуждалось подобное поведение графических 3D-ускорителей Adreno.

Повышать минимальную версию Android OS до 4.2 (API 17) мне решительно не хотелось и я начал искать подходящие способы устранения проблемы. Наиболее правильное и очевидное решение состоит в том, чтобы рисовать каждый кадр полностью, то есть в движке игры должен быть лишь один вызов функции SDL_GL_SwapWindow(). К сожалению, это бы потребовало множества серьёзных изменений в коде движка, детальный разбор того, как он работает, а вникать в это очень не хотелось. Я не сильный знаток OpenGL и OpenGL ES, но немного поэкспериментировав, я обнаружил, что если после каждого вызова SDL_GL_SwapWindow() вызывать такую вот функцию clearScreen():

То ситуация исправляется в лучшую сторону и баг в отрисовке полностью пропадает. Но в расход идёт фоновая картинка, было:



Фоновая картинка в игровых меню, скриншот с Motorola Droid 4 (превью, увеличение по клику).

Стало:



Отсутствие фоновой картинки в игровых меню, скриншот с Motorola Droid 4 (превью, увеличение по клику).

Помимо добавления этой функции, пришлось ещё серьёзно подрихтовать вложенные меню и внутриигровые окна, вынося их отрисовку на передний план. К счастью, потеря фона оказалась не столь страшной, главное, что картинка теперь нормально отображается на всех моих устройствах. Возможно, когда у меня появится немного больше свободного времени, я перепишу отрисовку движка без использования технологии «грязных прямоугольников».

После того, как я получил тестовую сборку LAB3D/SDL, не имеющую проблем в отрисовке как на Adreno, так и на PowerVR, я решил проверить работу движка на старых устройствах с Android OS 2.3 и PowerVR SGX530. Здесь я снова наткнулся на неполадку: почему-то размер глубины цвета OpenGL ES-контекста устанавливался только в 24 бит, но не в 16 бит. Мне пришлось повысить глубину цветности в проекте, что, кстати, в лучшую сторону сказалось на качестве отображаемой картинки, было:



Глубина цвета 16 бит, фрагмент скриншота с Motorola Droid 4.

Стало:



Глубина цвета 24 бита, фрагмент скриншота с Motorola Droid 4.

Движок LAB3D/SDL кроме, непосредственно, OpenGL использует специальную библиотеку-надстройку над ним, называемую GLU (OpenGL Utility Library). Поскольку в Android OS нет этой нативной библиотеки, мне пришлось использовать её порт на OpenGL ES, который называется GLU ES и доступен под свободной лицензией SGI FREE. GLU ES распространяется вместе со специальной библиотекой для тесселяции TESS, которая по сути бесполезна для LAB3D/SDL, поэтому её исходные коды можно не включать в проект.

Кстати, ещё патчи от Pickle исправили ситуацию с вводом текста во внутриигровых окнах, что пришлось весьма кстати, ведь многие устройства на Android OS, как и портативные игровые консоли, не имеют полноценной физической клавиатуры.

<< Перейти к содержанию

3. Интересная проблема с отображением некоторых PNG-текстур

При тестировании сборки LAB3D/SDL на своих устройствах я обнаружил ещё один странный баг, который заключался в том, что некоторые подгружаемые PNG-текстуры высокого разрешения отображались битыми:



Битая PNG-текстура, скриншот с Motorola Photon Q (превью, увеличение по клику).

А так должно быть:



Нормальная PNG-текстура, скриншот с Motorola Photon Q (превью, увеличение по клику).

При этом на компьютерной сборке движка ничего подобного замечено не было. Оказалось, что по какой-то причине на мобильных устройствах альфа-канал на этих текстурах не определяется, хотя он там точно присутствует. Пришлось явно выставить для всех текстур GL_RGBA, вместо GL_RGB, так как они абсолютно все используют альфа-канал.

<< Перейти к содержанию

4. Освобождение от библиотеки SDL_image 2.0

Улучшенная jspenguin’ом версия LAB3D/SDL для подгрузки текстур высокого разрешения в формате PNG использует библиотеку SDL_image 1.2, соответственно при портировании на SDL 2.0 я задействовал SDL_image 2.0, которая как раз и предназначена для работы с SDL-библиотекой новой версии. Но поскольку SDL_image 2.0 имеет слишком большой размер и избыточную для меня функциональность, я решил полностью отказаться от её использования и воспользоваться альтернативой. Такой альтернативой оказалась небольшая библиотека LodePNG, состоящая всего из двух файлов: заголовочного и исходного. Она предназначена только для загрузки и обработки PNG-файлов и не является таким всеядным комбайном, как SDL_image 2.0, которая работает со множеством различных форматов изображений. Переписанная функция подгрузки текстур стала выглядеть следующим образом:

Благодаря использованию LodePNG размер установочного APK-пакета уменьшился на целый мегабайт.

<< Перейти к содержанию

5. Дополнительные возможности для Android OS в SDL 2.0

Поскольку поддержка Android OS у SDL 2.0 теперь официальная, то разработчики реализовали несколько удобных возможностей, которые позволяют получить доступ к различным местам хранения игровых данных. К примеру, чтобы открыть файл texture.bin, который хранится в APK-пакете в каталоге assets, достаточно воспользоваться функцией SDL_RWFromFile():

Как это обычно делается и на других платформах. Но не стоит забывать, что assets’ы имеют доступ только для чтения, поэтому если в файл будет записана какая-либо информация, его необходимо куда-нибудь скопировать, например, во внутреннее хранилище, доступное как для чтения, так и для записи и записывать информацию уже там. У себя в LAB3D/SDL я имею пару таких файлов, поэтому я написал небольшую функцию copyFileFromAssetsToInternalRWDirAndroid(), которая занимается их копированием во внутреннее хранилище:

С помощью специальных функций, в названии которых встречается слово Android, можно получить путь и доступ к различным областям хранения, узнать их состояние или получить указатель на окружение JNI. Я использовал функцию SDL_AndroidGetInternalStoragePath() для доступа к внутреннему хранилищу и скопировал необходимые файлы:

В заголовочном файле jni/SDL2-2.0.4-compact/include/SDL_system.h задекларирован список всех доступных платформозависимых функций, которые помогут взаимодействовать с Android OS.

<< Перейти к содержанию

6. Java-обёртка и лаунчер

Порт SDL 2.0 на Android OS работает следующим образом: большинство Android-приложений написаны на языке Java, но опционально они могут обращаться к функциям нативных библиотек на C/C++. SDL-приложения написаны на языках C/C++ и официальный порт использует небольшую Java-прослойку, которая с помощью JNI общается с SDL-библиотекой. Это означает, что SDL-приложение должно быть расположено внутри Java-проекта для Android OS, чтобы код на C/C++ имел возможность коммуникации с кодом на Java. Таким образом можно собрать стандартный установочный APK-пакет вашего SDL-приложения. Java-прослойка, реализующая Activity, располагается в файле src/org/libsdl/app/SDLActivity.java, она занимается загрузкой кода SDL-приложения и динамической SDL-библиотеки. Нативные функции, используемые Java-прослойкой, реализованы в файле jni/SDL2-2.0.4-compact/src/core/android/SDL_android.c. Для правильной работы SDL-приложения функция main() перед свои вызовом должна быть обёрнута специальным кодом, который располагается в файле jni/SDL2-2.0.4-compact/src/main/android/SDL_android_main.c, этот файл должен быть скомпилирован вместе с исходниками SDL-приложения.

Для того, чтобы внести какие-либо изменения в проект, например, изменить стандартное имя и идентификатор приложения, нужно отредактировать файл AndroidManifest.xml, затем создать исходный Java-файл с классом, который будет унаследован от SDLActivity. Данный способ можно использовать и для модификации методов родительского класса, достаточно их перегрузить. К примеру, в моём проекте унаследованный класс KenLab3DActivity выглядит следующим образом:

Кроме перегрузки родительского метода onCreate(), здесь у меня реализован ещё и метод doVibrate(), который я могу дёргать из нативного C/C++ кода SDL-приложения с помощью JNI.

Для изменения различных, часто используемых опций, я решил создать простой лаунчер, позволяющий сразу запустить движок с необходимыми параметрами. Как было отмечено в самом начале статьи, решено было сохранить оригинальное поведение игры, которое заключалось в следующем: при первом запуске игра запускает конфигуратор, в котором можно изменить различные опции и параметры. После выхода из конфигуратора создаётся специальный конфигурационный файл и при последующих запусках движок игры видит и читает этот файл, запуская, соответственно, уже саму игру. Файл после выхода из настроек создаётся во внутреннем хранилище приложения, а потому из самого лаунчера мы легко можем отследить его отсутствие или присутствие и, например, изменить название кнопки с Setup Ken’s Labyrinth! на Run Ken’s Labyrinth!:

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



Конфигуратор, отображающийся при первом запуске игры, скриншот с Motorola Photon Q (превью, увеличение по клику).

Для реализации лаунчера я создал отдельный класс KenLab3DLauncherActivity, набросал к нему простейший графический интерфейс с несколькими опциями и связал всё вместе, получилось следующее:



Готовый лаунчер для запуска игры, скриншот с Motorola Photon Q (превью, увеличение по клику).

В качестве небольшого украшения я вставил в лаунчер изображение с коробочной версии Ken’s Labyrinth и реализовал диалог About Game:



Диалог About Game, скриншот с Motorola Photon Q (превью, увеличение по клику).

Очень удобно, когда выставленные настройки сохраняются и не нужно снова настраивать игру перед её запуском. Для сохранения и восстановления выставленных параметров я задействовал класс SharedPreferences. С помощью этого класса можно сделать так, чтобы настройки приложения восстанавливались после его запуска и сохранялись после выхода из лаунчера. Для хранения настроек я создал вложенный класс KenLab3DSettings:

К некоторым параметрам можно обращаться из нативного C/C++ кода с помощью JNI следующим образом:

Подобные JNI-функции я вынес в отдельный файл, который назвал androidutils.c, теперь достаточно вызывать эти функции во время инициализации игрового движка, чтобы применить к нему параметры, расставленные в графическом интерфейсе лаунчера.

Кстати, при тестировании приложения на Android OS 6.0.1, где ART включен по умолчанию, я заметил интересный факт: у меня в коде была небольшая ошибка — для получения значения переменной типа boolean я использовал метод GetStaticIntField(), вместо необходимого GetStaticBooleanField() и на ART приложение не запускалось, а на Dalvik‘е в Android OS 4.1.2 отлично работало.

<< Перейти к содержанию

7. Реализация сенсорного управления

Сперва для реализации сенсорного управления я решил использовать обычные стандартные кнопки, доступные в Android OS, именно таким способом я воспользовался в своём порте игры Spout. Когда я поместил кнопки на Layout, который совместил с OpenGL ES-контекстом игры, я ужаснулся, насколько всё получилось медленно. FPS сразу просел с шестидесяти до десяти. Стало понятно, что мне этот способ категорически не подходит. Я начал смотреть, как сенсорное управление реализовано в других играх для Android OS и совсем расстроился, поскольку в большинстве случаев сам нативный движок отображал и обрабатывал необходимые элементы управления. А в других случаях использовал достаточно объёмные библиотеки, вроде MobileTouchControls. Тогда я начал экспериментировать и мои эксперименты показали неожиданный результат: если вместо слоя с кнопками перекрыть OpenGL ES-контекст обычным прозрачным изображением, то FPS вообще не проседает. А если нарисовать на этом изображении полупрозрачные кнопки и отловить нажатия на дисплей устройства, то получится весьма неплохое сенсорное управление. Я занялся реализацией идеи и с помощью свободного графического редактора GIMP подготовил прозрачный холст с кнопками размером 854×480:



Изображение-холст с полупрозрачными кнопками (превью, увеличение по клику).

Осталось лишь разобраться, как расчитать и сопоставить координаты нажатий на экран с кнопками на изображении, ведь разрешение дисплея на устройствах под управлением Android OS различается и постоянно увеличивается. Для того, чтобы координаты совпадали, достаточно x и y нажатия делить на width и height физического разрешения экрана устройства, а затем координаты кнопок вычислить точно таким же способом, то есть x и y кнопки делить на размер подложки, то есть на 854 и 480 соответственно. Полученные относительные значения можно сохранить в прямоугольники, далее если координата попадает в прямоугольник — кнопка нажата, получается очень просто. Для этой цели мной был создан специальный класс KenLab3DTouchButtonsRects:

Внутри этого класса имеется вложенный класс KenLab3DButton, описывающий каждую кнопку. Координаты кнопок на изображении можно легко получить с помощью того же GIMP’а, только нужно брать верхний левый угол кнопки. Рассчитав все значения координат и добавив объекты кнопок в массив, я могу сопоставить с ними координаты нажатий. Для перехвата нажатия я немного измененил метод onTouch() класса SDLSurface, который находится в файле SDLActivity.java:

Первоначально реализованное мной управление не поддерживало нажатия более одной кнопки одновременно. Но немного позже я разобрался и реализовал MultiTouch. Обрабатываются прикосновения следующим образом: когда на экран нажимает один палец, прилетает событие ACTION_DOWN, при нажатии второго и последующих пальцев (при условии, что первый отпущен не был), генерируется событие ACTION_POINTER_DOWN. Когда какой-либо палец покидает экран, выполняется ветвь ACTION_POINTER_UP, а когда все пальцы покинут экран — ACTION_UP. Ещё имеется событие ACTION_MOVE, которое выполняется при любом движении пальцев.

Перекрытый изображением игровой OpenGL ES-контекст игры выглядит следующим образом:



Готовое сенсорное управление, скриншот с Motorola Photon Q (превью, увеличение по клику).

Теперь у меня получилось обработать несколько нажатий, а игрок получил возможность идти и стрелять, или, например, открыть дверь не убирая пальца с кнопки, отвечающей за движение вперёд.

<< Перейти к содержанию

8. Заключение, полезные ссылки и ресурсы

Портирование игры Ken’s Labyrinth на Android OS дало мне огромное количество ценного опыта. Я убедился в том, что порт библиотеки SDL 2.0 для Android OS получился весьма работоспособным. Я смог решить некоторые графические проблемы, связанные с работой OpenGL ES на разных устройствах и реализовал интересный способ сенсорного управления.



Порт игры Ken’s Labyrinth, запущенный на Android-устройстве Motorola Droid 4, демонстрация на видеохостинге YouTube.

Размер установочного APK-пакета получился весьма небольшим, всего лишь 1.8 МБ для одной архитектуры armeabi-v7a и 2.8 МБ для трёх официально поддерживаемых SDL 2.0 архитектур: armeabi, armeabi-v7a и x86.

Скачать APK-пакет Ken’s Labyrinth, готовый для запуска на любом Android-устройстве, можно по этим ссылкам:

[Скачать APK-пакет Ken’s Labyrinth, armeabi-v7a, 1.8 МБ | Download Ken’s Labyrinth APK-package, armeabi-v7a, 1.8 MB]
[Скачать APK-пакет Ken’s Labyrinth, armeabi, armeabi-v7a, x86, 2.8 МБ | Download Ken’s Labyrinth APK-package, armeabi, armeabi-v7a, x86, 2.8 MB]

Все исходные коды и проект в целом выложен в репозиторий на ресурсе Github. Мои изменения и исходные файлы доступны под лицензией MIT. Ссылка на репозиторий:

https://github.com/EXL/KenLab3d

В этой работе я использовал огромное количество материалов, основные из них я выделю в полезных ссылках ниже. Огромное спасибо ресурсам stackoverflow.com и google.com за то, что они есть.

  1. Официальная страница игры Ken’s Labyrinth на сайте Ken’а Silverman’а;
  2. Официальная документация SDL 2.0 для Android OS;
  3. Руководство по сборке SDL-приложений на Android OS;
  4. Руководство по миграции с SDL 1.2 на SDL 2.0;
  5. Сайт Jared’а Stafford’а, страница улучшений LAB3D-SDL;
  6. Официальная страница порта LAB3D/SDL от Jan’a Lönnberg’a;
  7. Порт LAB3D/SDL на OpenGL ES от Scott’a Smith’a.

Update 06-MAR-2017: Прочитать информацию о новой версии порта Ken’s Labyrinth v1.1 с незначительными исправлениями и улучшениями можно по этой ссылке.

Update 05-MAY-2017: Проект был переведён с устаревших технологий ant и Eclipse ADT на Gradle и Android Studio. Это ознаменовало выход новой версии Ken’s Labyrinth v1.2, скачать которую можно со странички проектов.

Update 16-SEP-2019: Ken Silverman добавил на официальную страничку Ken’s Labyrinth у себя на сайте информацию о моём портировании игры на Android OS.

<< Перейти к содержанию

Android, Dev

Комментарии: 6

    1. Если у меня появится время на доработку некоторых шероховатостей, в том же сенсорном управлении, то буду думать насчёт Google Play.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *