Лаунчер для Electronvolt

Майские праздники не прошли даром: на пару дней я основательно засел за Python и написал собственный лаунчер. Зачем? Он нужен для того, чтобы не привязывать игру к конкретной игровой платформе. В моем случае, я использую GameJolt, но такой подход работает для любого сервиса. Лаунчер служит посредником между игрой и API площадки. Все, что нужно делать игре — это сообщать лаунчеру о событиях наподобие «игрок получил такую-то ачивку». Лаунчер, в свою очередь, передает эти данные игровому сервису. Если надо переехать на другой сервис, достаточно просто обновить лаунчер, а игру патчить не придется — это удобно и экономит массу времени.

Для создания интерфейса я использовал WebView. Можно спорить до хрипоты о недостатках веб-стека, но на сегодняшний день он остается самым простым и универсальным решением для создания GUI. Нативные тулкиты платформозависимы, требуют соблюдения особой архитектуры приложения и чаще всего выглядят скучновато, а браузерный движок позволяет буквально за несколько часов наваять красивые формы с анимациями и спецэффектами — сделал и забыл!

Долгое время я писал веб-интерфейсы на CEF (Chromium Embedded Framework) — «Electron для Python». Он предоставляет portable браузерный движок и в целом свою задачу решает, но имеет ряд проблем. CEF Python уже несколько лет как не развивается, и версия Chromium в нем заметно устарела, новейшие свойства CSS не поддерживаются. Кроме того, в собранном виде CEF-приложение весит около 200 Мб, что для небольшого приложения, мягко говоря, жирновато. Все эти проблемы я решил переходом на PyWebView! Единственное, чем придется пожертвовать — совместимостью с Windows 8, что в 2025 году совсем не критично. Собранный PyInstaller’ом, лаунчер стал весить менее 50 Мб (используя UPX, можно сжать еще сильнее). А код под PyWebView гораздо компактнее и проще, чем под CEF Python.

Основная задача моего лаунчера — служить посредником между игрой и внешними сервисами. Для этого используется механизм IPC: игра отправляет события лаунчеру через TCP-соединение по кастомному протоколу. Например, когда игрок получает достижение, игра отправляет команду типа "eV:award=AchievementName". Лаунчер, получив такую команду, передает данные на сервер.

Важная особенность этого механизма — асинхронность: блокировать игровой цикл, чтобы отправить что-то по сети — не комильфо, задержки бывают в секунду и даже дольше. Выручил taskPool из std.parallelism — все вызовы IPC оборачиваются в task и заносятся в очередь пула задач:

taskPool.put(task!ipcSendSync(message));

Это не блокирует поток и обеспечивает плавный игровой процесс. Кроме того, очередь гарантирует, что вызовы будут обработаны последовательно — не будет состояния гонки за исходящий сокет, если отправить несколько сообщений подряд.

GameJolt имеет простой и удобный API, который легко интегрировать в проект. Однако, чтобы не компрометировать приватный ключ, я решил не внедрять его напрямую в игру. Вместо этого ключ хранится на моем сервере, который и отправляет запросы API. Лаунчер напрямую с API не взаимодействует — он общается только с сервером. Пользователь может по желанию авторизоваться в лаунчере, используя логин и токен GameJolt — токен был специально придуман, чтобы не сообщать играм пароль от аккаунта. В случае успешной авторизации достижения в игре будут синхронизироваться с аккаунтом.

Лаунчер также позволяет пользователю настроить графику игры перед запуском. Для этого он взаимодействует с конфигурационным файлом игры — settings.conf. Лаунчер считывает текущие настройки, обновляет их в зависимости от выбранных пользователем параметров и сохраняет изменения обратно в файл. Также он мониторит изменения в конфиге — если игра обновила файл, интерфейс лаунчера подхватит изменения.

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

Dagon 0.17 и другие обновления

Выпустил новую версию движка Dagon. Релиз включает поддержку экранов с высокой частотой обновления, поддержку Wayland под Linux, новые методы класса Application для управления окном приложения и методы класса Game для управления сценами. Шейдер HUD-объектов теперь поддерживает прозрачность материала. Исправлен баг с неправильным удалением из памяти сцен GLTF, также исправлен прыжок в контроллере персонажей Newton. Движок и расширения теперь используют самые свежие версии всех BindBC-биндингов.

bindbc-soloud обновлен до версии 0.2 — биндинг теперь поддерживает SoLoud 20200207.

Обновлена демка механики игры Electronvolt: добавил главное меню, опции, паузу и множество других мелких улучшений.

Статус по проектам

Начало года — неплохое время для того, чтобы поразмыслить над тем, что я буду делать в ближайшем будущем, и в какую сторону будут двигаться мои OpenSource-проекты. Также у меня есть ряд других направлений деятельности, о которых я тут еще не упоминал. Если интересно, читайте дальше.

К сожалению, далеко не все, что я делаю, имеет какие-либо перспективы серьезного развития. Некоторые из проектов остались на уровне любительских, другие я просто физически не успеваю развивать надлежащими темпами. Третьи — это своего рода эзотерика в сфере IT, понятная и интересная лишь единицам)

Dagon. Развивается, но медленно. В данный момент я работаю над версией 0.16, в которую войдут нововведения прошлого года: подповерхностное рассеивание и зонды освещения среды. Я планирую работать над движком и дальше, планы по нему довольно масштабные: так, я хочу сделать встроенный редактор на основе ImGUI — он будет генерировать исходники на D и вызывать DUB для сборки проектов, таким образом движок станет намного дружелюбнее для начинающих. Также в планах переписать стек постпроцессинга.

dlib. Понемногу развивается ветка 1.x, а вот 2.x пока заморожена. Исследую возможность поддержки прогрессивных JPEG.

Electronvolt (проект Atrium). Временно заморожен, но не исключено, что я к нему еще вернусь.

bindbc-wgpu, dusk и прочие наработки по WebGPU на D. Периодически обновляю, но для серьезного перехода на WebGPU пока нет мотивации и ресурса. Никаких особых планов на этот счет тоже нет.

dray. Новый проект — движок рейкастинга на основе dlib. Находится в разработке. Я в него переношу код из моего старого физ. движка dmech, а то пропадают даром хорошие алгоритмы) На сегодняшний день dray уже поддерживает пересечение луча с произвольной выпуклой геометрией, движок включает классы для таких стандартных тел, как сфера, параллелепипед, цилиндр, конус, эллипсоид. Тела могут быть произвольным образом трансформированы при помощи матриц 4×4.

Журнал FPS. Он жив-здоров, просто уже не имеет PDF-версии и существует в виде новостной странички. У меня есть идея окончательно объединить его с порталом Xtreme3D — думаю, это будет сайт или даже целая соцсеть по любительской разработке игр.

Этос Метамодерна. Telegram-канал для пространных философских рассуждений, которые по формату не подходят для других моих площадок.

Живопись и 3D-моделирование для стоков я окончательно забросил — коммерческий выхлоп там теперь уже нулевой, а времени работать для души совершенно перестало хватать.

Не упоминаю тут свои бизнес-процессы — это большая тема для отдельной статьи, и даже не одной.

Временная шкала моих проектов

Приводя в порядок архивы и вспоминая прошлое, решил зафиксировать информацию о моих 3D-движках и других OpenSource-разработках в виде интерактивной временной шкалы при помощи time.graphics — возможно, кому-то будет интересно:

Dagon

Прошу читателей этого блога извинить меня за редкие посты. Более полугода я не отчитывался по работе над Atrium — спешу заверить, что проект не похоронен, прогресс понемногу идет, просто чуть медленнее, чем хотелось бы. Последние несколько месяцев я был занят дипломной работой в институте, поэтому свободного времени для геймдева было крайне мало.

Те, кто следит за моей активностью на GitHub, могли заметить, что у меня появился новый репозиторий dagon — проект, который позиционируется как новая эволюционная ступень DGL. В процессе работы над Atrium я пришел к выводу, что в движке не хватает средств автоматизации некоторых рутинных задач. Например, управление памятью в типичном игровом приложении может быть почти полностью автоматизировано, поскольку выделение и высвобождение памяти происходит в специально задуманных паузах, таких как переключение между локациями (это не относится к играм с открытым миром с фоновой подгрузкой, но это уже специфический случай). Кроме того, в обсуждении на Reddit звучал вопрос, почему DGL не использует SDL2. Так родилась новая ветка движка, которую я решил сделать отдельным экспериментальным проектом.

На сегодняшний день Dagon включает следующие возможности:

  • Использование SDL2
  • Новая модель памяти на основе концепции владельца (owner), позаимствованной из Delphi
  • Модель образцов и компонентов (entity-component), позволяющая расширять функциональность объектов динамически, без наследования классов
  • Динамическая перезагрузка ресурсов при их модификации сторонним приложением без перезапуска игры
  • Поддержка форматов OBJ и IQM
  • Поддержка текстур PNG, JPG, TGA, BMP
  • Поддержка контейнера Box для ресурсов
  • Новая система материалов с разделением на фронтенд (набор параметров) и бэкенд (передатчик параметров графическому конвейеру — фиксированному или шейдерному, в зависимости от выбранной реализации бэкенда). Система позволяет использовать как стандартные материалы с известным набором параметров, так и создавать свои, специализированные
  • Некоторые компоненты, напрямую портированные из DGL — например, система событий, система освещения, рендеринг текста.
Как только будет дописана система материалов и поддержка формата DGL3, я начну портировать Atrium на новый движок.

Atrium в Блоге D

Atrium, dlib и другие мои главные проекты привлекли внимание авторов Блога D, где сегодня был опубликован соответствующий пост от Майка Паркера, автора Derelict. Это первый основательный отчет об Atrium на английском языке, если не считать анонса в ньюсгруппе.

http://dlang.org/blog/2016/09/16/project-highlight-timur-gafarov

Heat haze

Сделал эффект «искажения пространства», похожий на марево от жары — думаю применить его где-нибудь в игре:

x86_64! Ура, товарищи!

Наконец-то мне удалось собрать Atrium под 64-битную Windows! Пришлось ставить VS 2015, но оно стоило того…

Заодно проверил на практике LDC 1.0.0 — производительность, как и несколько лет назад, в разы выше, чем с использованием DMD, что не может не радовать. Теперь все тестовые сборки и промежуточные релизы будут собираться LDC и снабжаться 64-битными версиями.

Интерьер

Продолжаю работу над дизайном интерьера станции: