Pull to refresh

Стек технологий Shiro Games

Reading time 10 min
Views 7.3K
Original author: Nicolas Cannasse

Наш игровой движок Heaps.io и набор инструментов и технологий, на котором он основан, являются результатом опыта, накопленного за двадцать лет, посвященных созданию игр: сначала в компании Motion-Twin (создатели Dead Cells), а с 2012 года в Shiro Games (Evoland, Northgard и Darksburg).
Названные игры (2D и 3D) были созданы с использованием стека библиотек и инструментов, исходный код которых был открытым с самого начала, и которые продолжают развиваться и поддерживаться.
Так как меня часто спрашивают о том, как мы создаем игры, то я подумал, что было бы неплохо поделиться подробностями обо всех элементах технологического стека Shiro Games. Он прекрасно подходит для наших задач, так что возможно он может подойти и другим компаниям.


image


Сообщество Haxe / Heaps


Если у вас есть какие-либо вопросы или вы просто хотите обсудить представленные в этой статье технологии, вы можете связаться с сообществом Haxe / Heaps:



Нативный слой


image


Нативный слой в основном написан на C с небольшой долей C++. В повседневной работе нам редко приходится напрямую иметь с ним дело, поскольку вместо C / C++ мы работаем с языками более высокого уровня, где серьезные сбои (в основном) сопровождаются информативными сообщениями об ошибках.
Производительность очень важна для нас, потому что — хотя мы и не создаем AAA-игры — мы всё-таки хотим получить отличную графику и захватывающий геймплей в 60 фпс, и не хотим тратить при этом драгоценное время наших кодеров на микрооптимизации из-за ограничений низкоуровневого движка.



Основным компонентом этой стратегии является виртуальная машина HashLink — быстрая строго типизированная виртуальная машина для языка программирования Haxe. Ее можно сравнить с JavaVM или Mono (используется в Unity), но при этом HashLink VM больше ориентирована на игры в реальном времени.


Игра компилируется в кроссплатформенный файл .hl, который можно запустить с помощью HashLinkVM JIT. Также байткод HashLink может быть сконвертирован напрямую в код на C, который затем можно скомпилировать с помощью любого компилятора — такой путь мы используем для консольных портов наших игр для PlayStation, Xbox и Nintendo Switch.
HashLink VM отлично работает как для классического объектно-ориентированного, так и для функционального стилей программирования. Она хорошо себя показывает в вычислениях с плавающей точкой, что важно для игр. Также данная виртуальная машина была разработана таким образом, чтобы дополнительные затраты памяти для работы сборщика мусора были минимальными. Например, наша 3D-игра Northgard использует менее 500 МБ памяти.


Так как HashLink — виртуальная машина, то это значит, что для вашей игры (или приложения) не будет различия между отладочной и релизной сборками (только если вы не скомпилируете свой код в C), игра всегда будет работать так же, как и на компьютерах игроков, на полной скорости, и при этом всегда можно будет получить полный стек вызовов.


Нативные библиотеки


Хотя HashLink поставляется только с небольшой стандартной библиотекой, ее возможности могут быть расширены с помощью дополнительных библиотек (написанных на C), предоставляющих доступ к новым API. Написание таких библиотек потребует от разработчика некоторых знаний об устройстве виртуальной машины и о том, как работать со сборщиком мусора, но это довольно несложный процесс. При правильной реализации можно легко изолировать ошибки, возникающие на низком уровне, от ошибок в логике приложения.


На данный момент с HashLink распространяются такие нативные библиотеки как: SDL2, DirectX11, OpenAL (работа со звуком), LibUV (сокеты), SSL (шифрование) и FMT (для работы с Zip, Ogg, Png, Jpg) а также ряд библиотек для работы с другими форматами файлов.
Исходный код перечисленных библиотек открыт и является частью репозитория HashLink.


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


Нативные инструменты


Низкоуровневые инструменты необходимы для анализа производительности разрабатываемых приложений. В Shiro Games мы используем следующий набор инструментов:


  • В HashLink VM есть встроенный отладчик, имеющий интеграцию с Visual Studio Code
  • Для анализа использования CPU недавно был разработан HashLink CPU Profiler. Работа данного профилировщика не замедляет работу анализируемого приложения на HashLink
  • Для измерений потребления памяти и обнаружения утечек, вы можете либо замерить все выполненные аллокации, либо сделать дамп памяти для последующего анализа с помощью Memory Profile API (к сожалению данное API на данный момент не задокументировано)
  • Для измерения производительности графической подсистемы мы используем инструменты, предоставляемые вендорами GPU, например, NVIDIA Nsight.

Уровень языка программирования


image


Рассмотрев нативный уровень (обозначен на схеме зеленым), перейдем по стеку к уровню языка программирования.


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


Конечно, как главный разработчик языка Haxe, я немного предвзят, но каждому программисту в Shiro действительно нравится работать с Haxe, и это критически важный инструмент для нашей повседневной работы. Кроме того, мы наняли разработчиков с различным опытом программирования (C++, C#, JavaScript, Python, Java и т.д.), и все они смогли быстро адаптироваться к Haxe и писать эффективный код.


Haxe — это кроссплатформенный язык программирования, который может компилировать код под множество различных платформ. В Shiro мы используем в основном две платформы: HashLink для наших игр и JavaScript для наших инструментов (подробнее об этом далее).
Некоторые популярные инди-игры также были созданы с использованием Haxe (но без HashLink или других представленных в данной статье инструментов), например: Papers Please, Brawlhalla, Dicey Dungeons и др.


Haxe поддерживается как независимый проект с открытым исходным кодом. Поддержка осуществляется Haxe Foundation, который финансируется несколькими крупными компаниями, использующими Haxe для разработки кроссплатформенных приложений и игр.


Узнать больше о Haxe вы можете на его официальном сайте.


Игровой движок: Heaps.io


image


Heaps.io — игровой движок, лежащий в основе игр Shiro Games. Он обеспечивает:


  • 2D рендеринг
  • 3D рендеринг
  • Обработка звука
  • Управление (клавиатура, мышь, геймпад)
  • Управление ресурсами.

Он построен так, чтобы отделить реализацию низкоуровневых функций для поддержки платформ от графической логики / данных среднего уровня. Такая архитектура позволяет интегрировать новый рендерер или поддержку новой платформы — для этого достаточно просто портировать несколько классов (при условии что у вас уже есть соответствующие нативные библиотеки для HashLink). На данный момент Heaps.io поддерживает следующие платформы / графические API:


  • HashLink и DirectX11
  • HashLink и OpenGL / SDL2
  • HashLink / C и NVN (нативное графическое API в Nintendo Switch SDK)
  • HashLink / C и GNM (нативное графическое API в PS4 SDK)
  • HashLink / C и Xbox One SDK
  • JavaScript и WebGL2

Примечание: обозначение "HashLink / C" означает, что для указанной платформы возможно использовать только компиляцию из байткода HashLink в C (JIT VM на данных платформах не доступен).


image


Heaps.io задумывался как легковесный движок, который можно легко адаптировать под нужды пользователей. Он предоставляет 2D / 3D граф сцены, и поведение каждого объекта на сцене можно доработать. Рендерер и система освещения также могут быть полностью заменены, что позволяет написать собственный конвейер рендеринга, отвечающий требованиям конкретной игры.


И 2D и 3D используют аппаратное ускорение на GPU и основаны на GPU-шейдерах. Heaps поставляется с собственным встроенным языком шейдеров HxSL. HxSL — мощный инструмент, поскольку вместо необходимости написания одного большого шейдера он позволяет написать отдельные небольшие шейдерные эффекты, которые затем собираются вместе и оптимизируются во время выполнения программы.


Система управления ресурсами в Heaps.io вынесена в отдельный расширяемый фреймворк. Кроме того, Heaps.io предоставляет средства для «запекания ресурсов» — автоматической конвертации и упаковки ресурсов в более подходящий для движка формат (например, для ресурсов, получаемых на выходе из Photoshop, Maya, Blender и т.д.)
Больше информации о Heaps вы найдете на его официальном сайте, в разделе документации.


Редактор HIDE


image


HIDE (Heaps IDE) — это отдельное приложение, которое позволяет создавать средства для просмотра и редактирования 2D / 3D-контента.
HIDE — это HTML5-приложение, в котором запущен инстанс движка Heaps.io в режиме WebGL2, что позволяет очень быстро разрабатывать пользовательские интерфейсы, используя Haxe и HTML / CSS.


На данный момент HIDE предоставляет следующие средства:


  • древовидный список ресурсов
  • просмотрщик 2D текстур
  • просмотрщик 3D моделей в формате FBX и редактор материалов
  • редактор 2D и 3D эффектов на основе временной шкалы (timeline based effects)
  • редактор 2D и 3D частиц
  • редактор 3D-уровней (на скриншоте ниже показан уровень Darksburg)
  • редактор Префабов
  • редактор скриптов (с использованием hscript)
  • редактор графа шейдеров [работа над ним пока что не окончена]

image


HIDE ориентирован на обработку данных (data-oriented) и основан на модели Префабов (класс hrt.prefab.Prefab). Эта модель хранит данные редактора и может по запросу создавать экземпляры эффектов, уровней и т.д.; также она является поставщиком данных для движка, который затем обрабатывает их в соответствии с заложенной вами игровой логикой.


Поскольку модель Префабов расширяемая и в HIDE реализована поддержка плагинов, то в HIDE есть возможность добавлять пользовательские компоненты и редакторы.


Исходный код HIDE разделен между пакетами hide (содержит код IDE), и hrt (содержит классы, которые можно использовать как часть игрового клиента).


К сожалению, в настоящий момент документация для HIDE практически отсутствует и мне еще предстоит поработать над ней.


DomKit UI Toolkit


image


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


Используемая семантика CSS частично соответствует стандартам HTML5, но модель разметки специфична для Heaps.io и больше подходит для UI / UX в играх.


image


Также вы можете объявлять собственные компоненты, добавлять дополнительные свойства и код, описывающий как CSS должен применяться к свойствам ваших компонентов.
Кроме того, библиотека DomKit полностью автономна и может использоваться совместно с любыми UI фреймворками (но в Heaps.io поддержка DomKit уже реализована).
Узнать больше о DomKit вы можете из его документации.


Castle DB


image


Castle DB — один из самых важных инструментов для повышения производительности, который используется в Shiro Game. Это статическая структурированная база данных, с которой работают наши геймдизайнеры — редактируют все данные, используемые в игре (списки предметов, локаций, NPC, деревьев технологий, навыков и т.д.).


Используя IDE Castle DB, можно задавать и изменять структуры данных, а затем вводить данные в соответствии с описанием этих структур. В этом отношении IDE Castle DB является своего рода специализированным редактором электронных таблиц для игр.


image


Кроме того, используя макросы Haxe, можно напрямую получить все структуры данных, объявленные в CDB-файле, а также перечисления (enums) для всех уникальных идентификаторов для различных типов игровых объектов / уровней / и т.д.


// Data.hx
private typedef Init = haxe.macro.MacroType<[cdb.Module.build("data.cdb")]>;

Данные в CDB хранятся в виде текстового файла в формате JSON, что дает возможность совместно работать с данными, используя систему контроля версий (слияние, различие, разрешение конфликтов и т.д.).


Castle DB раньше был отдельным редактором (его старую версию можно скачать с его веб-сайта), но теперь он интегрирован в HIDE, благодаря чему можно использовать данные CDB для Префабов в редакторе уровней и т.д.


Узнать больше о Castle DB вы можете на сайте castledb.org.


HScript


image


HScript — это небольшой парсер и интерпретатор скриптов, синтаксис которых основан на синтаксисе Haxe. Таким образом у геймдизайнеров есть возможность самостоятельно вносить изменения в коде, не прибегая к помощи программистов и не пересобирая клиент.


Одна из самых приятных вещей в HScript — это то, что он позволяет вносить изменения в скрипт на этапе между парсингом и выполнением скрипта. Например, класс Async преобразует скрипт в асинхронный код.


image


Совсем недавно я добавил в HScript возможность проверки типов в скриптах, данный механизм работает примерно также как в компиляторе Haxe. Это позволило добавить в редактор скриптов, встроенный в HIDE, автодополнение кода и проверку типов прямо во время их написания (о том, как добавить поддержку собственных типов, можно почитать в вики), что должно помочь геймдизайнерам совершать меньше ошибок и повысить их продуктивность.


HScript также интегрирован в CDB / Hide, что позволяет назначать объектам скрипты и т.д.
Исходный код библиотеки доступен на github, а установить ее можно с помощью команды haxelib install hscript.


HxBit


image


HxBit — это библиотека для сериализации и сетевой синхронизации. Она позволяет помечать свойства ваших классов, которые должны быть сериализованы (для сохранения) и / или переданы по сети при их изменении (для многопользовательских игр).


Полная документация доступна в вики.


MPMan


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


  • аутентификация игрока на разных платформах
  • многопользовательская система лобби, рейтинги, запрос инстансов игровых серверов
  • приглашения для многопользовательской игры
  • достижения
  • обнаружение DLC и всплывающие окна магазинов
  • хранение (кроссплатформенная обработка пользовательских сохранений).

Заключение


Вот и все (пока). Я надеюсь, что после прочтения этой статьи у вас сформировалось некоторое представление о том, как мы делаем игры в Shiro. Также я надеюсь, что заинтересовал вас попробовать некоторые, если не все, из представленных инструментов.


Я написал и продолжаю поддерживать многие из этих инструментов. В этом деле хорошую помощь оказывают и программисты Shiro и члены сообщества Haxe, и я благодарен им за это! Я думаю, что для отличной работы необходимо иметь хорошие инструменты, и каждый из инструментов, представленных здесь, оказался полезным в нескольких реальных проектах. Я вполне доволен достигнутыми результатами, и поэтому решил, что пришло время рассказать о них.


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


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


Наконец, хочу упомянуть, что Shiro Games активно ищет разработчиков для работы над увлекательными, но еще не анонсированными проектами. Вы можете связаться со мной в Twitter и посмотреть список наших вакансий.

Tags:
Hubs:
+6
Comments 9
Comments Comments 9

Articles