[Из песочницы] Как создавался кроссплатформенный Half-Life или «Хедкрабы внутри ваших часов»

1d97102c456e4d239f12e90aa559e7aa.jpg

Парочку месяцев назад на Гиктаймсе проскакивала новость о запущенной Half-Life на Android Wear. В статье ни слова не сказано было о разработчиках и тогда один из хабровчан спросил в комментариях, почему никто из них не напишет здесь?

И вот уже годовщина с того момента, как я начал порт свободного движка Xash3D на Linux, а также, поскольку несколько моих знакомых всё же интересовались подробностями, я решил написать этот пост. Кому интересна история проекта, обходы разных проблем и мои личные советы, прошу под кат.
Начну с истории проекта. Следил за движком я ещё с 2012 года, но лишь осенью 2014 с небольшим опытом программирования на С++ я скачал исходный код движка. Загоревшись мыслью о том, что свободный игровой движок и кроссплатформенность — понятия ещё с кармаковских времён тесно связанные, я начал портировать его на Linux.

Поначалу порт планировался с использованием winelib, но со временем, вникнув в архитектуру движка, я остановился на SDL2, как самой вездесущей мультимедийной библиотеке. Да и Valve для своих портов использовали его.

И вот сразу мой первый совет тем, кто хочет переносить любое неизвестное ему приложение на любую ОС:

1) Создавайте проектные файлы сразу и, не делая ни единого изменения в проекте, компилируйте его.

Да, от моего совета ваша IDE может даже подвиснуть, так как компилятор выдаст не одну тысячу ошибок и предупреждений. У меня компилятор выдавал около 4000 ошибок.

Переходя от одной ошибки к другой, я постепенно избавлялся от них. Не оставалось и виндового кода, -Wl,--no-undefined очень сильно спасает при портировании.

И вот свершилось — загрузился движок. Показывает собственную консоль, а за окном, тем временем, уже было примерно начало декабря прошлого года. Должен подчеркнуть, что до меня попытки предпринимались и примерно на консоли и заканчивались, если не раньше. Весь декабрь ушёл на загрузку библиотек в рантайме, SDL ввод, звук — и вот я выкладываю на Linux.org.ru скриншот работы.

Скриншоты, сделанные за декабрь
d8a202f545894461bb2403aa711a5df9.jpg

То, что я скидывал когда-то EXL.

8c11323e151c47e7bb18fca30ce8dcf0.jpg


Первый публичный скриншот
84f52f5248834c1b88d671236b2cbc55.png


Несколько человек заинтересовываются проделанной работой. Я же оглядываюсь на исходники и понимаю, что с этим уже работать нельзя: во многих местах код из-за макросов становится нечитабелен, появляются странные баги, сборка за пределами моего локалхоста очень сложна. Да и версия движка сильно старая. В комментариях к треду указывают, что новые версии распространяются на каком-то другом форуме. В итоге я начинаю всё с нуля, а мой знакомый помогает приводить всё в серьёзный вид — переводит сборку на CMake, гонит на меня плохо пахнущими тряпками за слишком большие коммиты и говнокод. Также на GitHub создаётся организация SDLash3D, названная в честь старого порта. На момент написания статьи в ней аж пять человек, но активны только двое.

Внезапносовет номер 2, который я для себя уяснил в этом время:

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

Также тут совет для тех, кто, читая эту статью, пишет код в своей студии.

3) На счёт всякого подозрительного и странного кода обращайтесь к Google. Он вам расскажет, что ваш код компилируется только под Visual Studio, у которого много нестандартных расширений. И поменьше завязывайтесь на WinAPI.

Тем временем, nicknekit/Unc0nnected молча начинает портировать старый порт на Android.

Скриншоты и видео, любезно предоставленные Никитой
b492e0226b17465aaaa3191547ec2dac.jpg

1e56ab3d27fd4ceea4935946847f1a30.jpg



С февраля мы с Никитой начинаем работать вместе над портом. Он занимается старым портом, а я допиливаю новый и переношу в него функционал, связанный с Android.

В этот момент устанавливается базовая схема работы порта на Android. Сейчас оно выглядит так:

7d5b1b5988674db9a7d9d75da1b9f11f.png

В марте мы создаём тред на 4PDA, о котором сообщаем об успехах переноса, новые видео и скрины. Первого же апреля выходит версия 0.1, но первое апреля не может быть без шутки, поэтому в движке сделано специально условие, при котором он закрывается, если не найден pakandroid.pak, в котором был «зашит» очень весёлый и достаточно качественный мод G-Man Invasion.

С тех пор, среди значимых событий для порта оказались:

  • Поддержка сенсорного управления, сделанная совместно с Beloko Games;
  • Релиз версии 0.14, который действительно принёс успех. Около 20 тыс. посетителей за два дня, судя по статистике на GitHub;
  • Интерфейс Android-версии для модификаций, сделанный нашим mittorn. Мододелы могут самостоятельно выпустить свою игру ещё и на Android.


На этом можно и закончить, ниже бонус в виде отдельных коммитов и ссылки на нас на GitHub и ModDB.

Бонус №1. Несколько коммитов, связанных с разным пониманием кода в Visual Studio и GCC. После исправления их всех я точно уверен, что поддержка Си в студии — это худшее, что случалось в сфере программирования:


Бонус №2. Также некоторые коммиты, связанные с ARM, Android и OpenGL ES:

  • Баг, со странным умножением и делением на 1.0 на ARM;
  • Ещё проблемы с float. Вызывало рандомные краши с SIGBUS;
  • А здесь ссылки нет. Просто внезапно для себя открыл, что все char на ARM — беззнаковые. Оттого навигация NPC сходила с ума, а в движке не работали спрайты. Можно или ключ -fsigned-char вставить, или явно указывать, что char должен быть знаковым для этой переменной;
  • Баг рендера. Не совсем проблемы ARM, зато проблема OpenGL ES. До сих пор не пофикшена полностью;
  • Своя собственная реализация dlsym() на Android, а всё потому что в Android до Lollipop просуществовал баг, с которым не резолвились некоторые символы из библиотек;


Ссылки:

Организация на GitHub.
Страница на ModDB.

Спасибо за внимание, ваш a1batross.

© Habrahabr.ru