По просьбам любопытствующих создал канал, в котором буду делиться мыслями и прогрессом в разработке игрового движка с открытым исходным кодом. Ознакомиться с репозиторием можно здесь.
GitHub
GitHub - thunder-engine/thunder: Thunder Engine – Cross-platform 2D and 3D game engine with modular architecture
Thunder Engine – Cross-platform 2D and 3D game engine with modular architecture - thunder-engine/thunder
🔥4
Thunder Engine Development pinned «По просьбам любопытствующих создал канал, в котором буду делиться мыслями и прогрессом в разработке игрового движка с открытым исходным кодом. Ознакомиться с репозиторием можно здесь.»
Итак, немного о движке. Движок я начал разрабатывать примерно в 2007 году. До этого долго вынашивал идею. В то время движков было очень не много и многие писали свои. Я тоже решил пойти по этому увлекательному пути. За это время (почти 20 лет) движок 3 раза переписывался с нуля и каждый раз архитектура казалась все лучше и лучше. Последнее "переписывание" ядра было примерно 6-7 назад. И кажется сейчас, она выглядит достаточно стабильной и гибкой.
❤2
О возможностях движка. Движок написан на языке С++. Имеет редактор и утилиты для финальной сборки игрового билда. Он разрабатывается по модульному принципу. Пользователи могу добавлять собственные модули расширяя возможности как самого движка так и его редактора.
На данный момент я написал несколько основных модулей для работы с графикой:
- Рендер (OpenGL)
- Редактор Материалов (Shader Graph)
- Редактор текстур (Работа с атласами и прочее)
- Редактор эффектов
Так-же есть модуль отвечающий за обработку физики на основе Bullet3
Модуль скриптового движка (Angel Script)
А так-же ряд различных конвертеров игровых ресурсов.
На данный момент я написал несколько основных модулей для работы с графикой:
- Рендер (OpenGL)
- Редактор Материалов (Shader Graph)
- Редактор текстур (Работа с атласами и прочее)
- Редактор эффектов
Так-же есть модуль отвечающий за обработку физики на основе Bullet3
Модуль скриптового движка (Angel Script)
А так-же ряд различных конвертеров игровых ресурсов.
🔥2
Цель проекта не сделать "убийцу" UE5 или Unity, а сделать небольшой, удобный движок сопоставимый по качеству с Godot. Догнать любой из этих движков в одиночку НЕ ВОЗМОЖНО! Чисто человеческий ресурс не даст сделать это. Поэтому я просто пишу движок и стараюсь получить от этого удовольствие. Написание движков дает очень хороший буст к планированию архитектур и пониманию как оно работает "под капотом". Эти навыки были применены в различных профессиональных областях. Так, что если вам интересно, добро пожаловать в эту глубокую кроличью нору. 😏
🔥6
Во всех игровых движках можно выделить 3 основных части:
1. Система игровых ресурсов - это загрузка ресурсов с диска или процедурная генерация.
2. Обработка игровой логики - отвечает за организацию игрового цикла и правила игры.
3. Вывод результатов работы - это рендеры графики, источников звука и т.п.
Так-же можно выделить (опционально) систему синхронизации состояний между игроками.
Основой всех игр являются данные, поэтому поговорим о системе ресурсов в Thunder Engine. Есть несколько базовых типов ресурсов и несколько вспомогательных. Полный список и их назначение я сейчас приводить не буду.
Во только некоторые из них:
- Texture - Ресурс хранящий в себе картинку которую можно показать на экране (Используется материалом)
- Material - По сути представляет из себя набор шейдеров, определяющих как визуально будет выглядеть объект. (Его цвет и фактура)
- Mesh - Ресурс отвечающий за форму игрового объекта. Состоит из набора треугольников и дополнительных служебных атрибутов.
Thunder Engine использует собственный формат хранения ресурсов. Он нужен для обеспечения скорости загрузки и избегания использования различных загрузчиков в момент работы игры. Конвертация ресурсов происходит в момент импорта ресурсов в редакторе. Конвертированная версия ресурса сохраняется в отдельню папку, для последующей упаковки.
1. Система игровых ресурсов - это загрузка ресурсов с диска или процедурная генерация.
2. Обработка игровой логики - отвечает за организацию игрового цикла и правила игры.
3. Вывод результатов работы - это рендеры графики, источников звука и т.п.
Так-же можно выделить (опционально) систему синхронизации состояний между игроками.
Основой всех игр являются данные, поэтому поговорим о системе ресурсов в Thunder Engine. Есть несколько базовых типов ресурсов и несколько вспомогательных. Полный список и их назначение я сейчас приводить не буду.
Во только некоторые из них:
- Texture - Ресурс хранящий в себе картинку которую можно показать на экране (Используется материалом)
- Material - По сути представляет из себя набор шейдеров, определяющих как визуально будет выглядеть объект. (Его цвет и фактура)
- Mesh - Ресурс отвечающий за форму игрового объекта. Состоит из набора треугольников и дополнительных служебных атрибутов.
Thunder Engine использует собственный формат хранения ресурсов. Он нужен для обеспечения скорости загрузки и избегания использования различных загрузчиков в момент работы игры. Конвертация ресурсов происходит в момент импорта ресурсов в редакторе. Конвертированная версия ресурса сохраняется в отдельню папку, для последующей упаковки.
❤3🔥1
Вторым неотъемлемым компонентом игры является игровая логика. в Thunder Engine базовым объектом является Actor. Вы найдете много схожих черт с GameObject в Unity. Каждый Actor может вмещать в себя коллекцию различных Компонент (Component) эти компоненты могут отвечать за различные аспекты игрового процесса. Отображение игровых ресурсов (Mesh, Sprite и т.п.). Источники звука. Триггеры и прочее. Пользователи могут создавать свои компоненты и добавлять их к Актерам на сцене. (Опять же очень похоже на Unity не так ли?). В целом для упрощения работы с движком, я постарался сделать API похожим на популярные решения. Так будет проще для всех. 😇
❤3🔥1
Последним столпом ядра движка являются Системы. Системы это невидимые пользователю труженики, обеспечивающие последовательность обработки игрового цикла. К примеру ResourceSystem отвечает за жизненный цикл всех игровых ресурсов. Она загружает их с диска и удаляет их когда они больше не требуются. RenderSystem отвечает за отрисовку игрового мира. Есть системы для обработки физики. Скриптовых сценариев и прочие веселые штуки. Обычно система работает либо с компонентами принадлежащими ей либо с ресурсами. Разумеется разработчики могут добавлять собственные системы в игровой цикл.
❤3
Итак после небольшого экскурса в историю и подводки к базовой архитектуре движка. Настало время рассказать чем я занимаюсь на данный момент. Чтош приступим. Относительно недавно я занялся рефакторингом модуля отвечающего за пользовательский интерфейс. В предыдущей версии вся система виджетов была частью основного ядра. Решение это было вынужденное и связанное с зависимостями на соседние модули. Благо их удалось развязать и выделить GUI в отдельный модуль. Что в свою очередь даст возможность отказаться пользователям от лишнего (если их не устроят мои кнопочки и панельки). Но это еще не все. Я обратил внимание на UI Toolkit в Юнити и некоторые полезные фичи решил сделать и у себя.
Встречайте:
UiLoader - компонент который может принимать в себя новый ассет UiDocument представляющий из себя xml репрезентацию вашего UI. Так-же этот XML можно положить из кода и он загрузит его! Чудеса не так-ли?
StyleSheet - Новый тип ассетов который представляет из себя CSS файл. Да да! Тот самый CSS!
Так-же CSS стили можно настраивать и из XML документа.
Разумеется система реализована очень базово и CSS возможности сильно обрезаны. Но фундамент заложен и в дальнейшем возможности можно будет расширять!
Встречайте:
UiLoader - компонент который может принимать в себя новый ассет UiDocument представляющий из себя xml репрезентацию вашего UI. Так-же этот XML можно положить из кода и он загрузит его! Чудеса не так-ли?
StyleSheet - Новый тип ассетов который представляет из себя CSS файл. Да да! Тот самый CSS!
Так-же CSS стили можно настраивать и из XML документа.
Разумеется система реализована очень базово и CSS возможности сильно обрезаны. Но фундамент заложен и в дальнейшем возможности можно будет расширять!
❤3
Давненько хотел добавить поддержку формата Spine 2D. Эта задача лежала в бэклоге аж с 2018 года. Как быстро летит время! Наконец, я на это решился! Формат файла (в JSON варианте) вызывает двойственные чувства. С одной стороны, он кажется избыточным в некоторых полях. А с другой стороны рядом с JSON находится файл атласа, который выглядит как нашлепка. Я не понимаю, почему нельзя было эти данные положить в сам JSON файл? Я специально не хотел использовать существующие рантаймы для отрисовки спайнов т.к. приводит к дублированию функционала и, одновременно, усложняет интеграцию. Поэтому решил попробовать конвертировать структуру в известные моему движку компоненты и ресурсы. Да возможно не все фичи будут поддерживаться на старте (привет бленд шейпы) но я обязательно расширю недостающие элементы (когда-нибудь >_<)
🔥3❤1
Первые, вменяемые, результаты конвертирования из Spine2D. Пока поддерживается: Импорт одностраничного атласа с поворотами элементами в атласе. Импорт Иерархии скелета и размещении слотов для спрайтов на нем. А также, Импорт спрайтов в виде регионов и сеток (но не сеток для скелета). Еще много предстоит сделать. Очень хочется добавить поддержку сеток для скелета и анимацию. Самой последней частью интеграции будут бленд шейп анимации.
🔥4
Решил немного прерваться со спайном и поправить баги которые нашел Павел Танонов в редакторе. Т.к. скоро релиз очередной версии (по плану конец Марта), необходимо максимально отполировать найденные проблемы. Очень помогает взгляд на движок со стороны. Спасибо большое Паше за эту возможность!
🔥4❤3
Эх сколько раз я зарекался делать крупный рефакторинг перед релизом! Но каждый раз хочется что-то улучшить в архитектуре. Вот и сейчас решил переработать Sprite ассет. До этого этот тип ассета был Solid (все данные хранились в нем самом) к такому типу относятся простейшие ассеты, которые нельзя разделить (текстуры, меши и т.п.). Противоположностью solid ассетам являются ассеты-контейнеры. Контейнеры, обычно, содержат в себе ссылки на другие ассеты и дополнительные, внутренние параметры, отвечающие за соединение solid ассетов. В новом релизе Sprite будет ассетом контейнером. т.к. теперь он будет поддерживать несколько страниц текстур, а так-же различные шейпы, представленные в виде мешей. Такой подход, в теории, позволит в будущем использовать повторно некоторые элементы, что положительно скажется на потреблении памяти. После этого рефакторинга, возможно возникновение новых проблем и регрессий. Но, со временем, я их все отловлю! Обещаю!
❤4
Интересную багу нашел Павел в системе скриптов! На данный момент движок поддерживает программирование игровой логики на скриптовом движке AngelScript. Очень достойный и недооцененный движок с поддержкой ООП, компиляцией кода в исполняемый байткод (что ускоряет загрузку) и клевой виртуальной средой исполнения. Короче оказалось, что в редакторе между сессиями симуляции игрового процесса не сбрасывались глобальные переменные, что приводило к странному поведению игровых юнитов (они отказывались двигаться). Фикс занял условно 10 строк. Спасибо Паша!
🔥4❤3
Пока фикшу баги и готовлю релиз, расскажу немного о том, с какими сложностями сталкивается каждая архитектура, которая добавляет любой скриптовый движок. Сюда для удобства включу и C# и Java. Все дело в том, что эти движки работают на основе "managed" сред исполнения. Код написанный на этих движках компилируется в псевдо байт код (иногда вперемешку с реальным байт кодом). Так вот, если разработчик хочет вызывать из нативного кода (С++) функцию написанную скриптом или наоборот из скриптов вызвать код написанный на нативном языке. Для этого у скриптовых движков существует система регистрации "биндигов"
Биндинги это мостики между виртуальной машиной для исполнения и нативным кодом. Проблема в том, что эти биндинги приходится писать зачастую в ручную для каждого класса и для каждой функции. Если у вас много кода поддержка это безобразия превращается в сущий ад. Можно ли облегчить эту работу? Отчасти. Существенно, регистрацию байндингов облегчает так называемая "рефлексия". Рефлексией в программировании называется способность объекта рассказать о себе. Какие методы у него есть, какие свойства и другую важную информацию. К сожалению в C++ по умолчанию нет средств рефлексии классов. Разработчики вынуждены реализовывать ее самостоятельно. Но мы этого не боимся! Механизмы рефлексии есть во многих движках. Мета компилятор в UE, таблицы в Godot. Возможно что-то есть и в Unity. Но не факт! Используя рефлексию мы можем пройтись по всем известным нам классам и зарегистрировать их в системе скриптового движка. При изменении структуры класса, произойдет автоматическое обновление представление его в байндингах. К сожалению это работает только на классе поддерживающем рефлексию. Как правило унаследованном от базового класса типа "Object" для остальных классов и функций (математика, работа с файловой системой и пр.) по старинке приходится писать байндинги ручками. Но таких функций, благо, не много!
❤1🔥1🤯1
Как мы уже разобрали, рефлексия это полезно! Она помогает не только в работе со скриптовыми движками, но и с сериализацией объектов (способность объекта сохранять информацию о своем в буфер с дальнейшим сохранением на диск или отправкой по сети). Это очень существенный шаг от ООП к КОП (Компонентно Ориентированному Программированию). Общий принцип хранения информации о классе сводится к формированию специальных статических таблиц хранящих эту информацию. По необходимости эта информация извлекается и используется в ваших корыстных целях! Различия состоят лишь в том, каким образом формируются эти таблицы. По большому счету варианта 2. Либо программист заносит эту информацию в ручную и часто ошибается либо за него, ориентируясь по меткам, это делает Мета Компилятор. Мета компилятор это отдельная программа которая проходится по всем вашим исходникам и формирует эти таблички за вас. У обоих методов есть как плюсы, так и минусы:
Для ручного метода.
Плюсы:
- Не нужно писать утилиту отвечающую за парсинг и генерацию кода.
- Можно легко расширить и дополнить информацию.
Минусы:
- Необходимо описывать каждый класс вручную и поддерживать актуальность этих данных.
Для утилиты.
Плюсы:
- Автоматически обновляет все данные.
Минусы:
- Необходимо написать этот инструмент и встроить его в процесс построения игровых билдов.
- Расширение фичей может быть проблемным.
Для ручного метода.
Плюсы:
- Не нужно писать утилиту отвечающую за парсинг и генерацию кода.
- Можно легко расширить и дополнить информацию.
Минусы:
- Необходимо описывать каждый класс вручную и поддерживать актуальность этих данных.
Для утилиты.
Плюсы:
- Автоматически обновляет все данные.
Минусы:
- Необходимо написать этот инструмент и встроить его в процесс построения игровых билдов.
- Расширение фичей может быть проблемным.
Так как же обстоит дело с Thunder Engine? Хорошая новость в том, что в нем тоже есть рефлексия! Реализована она по первому принципу с небольшой модификацией предоставляющей небольшую защиту программиста от ошибок. Она основана на системе макросов и шаблонов. Позволяет разбирать методы и типы в полу автоматическом режиме. Подробней ознакомиться с ней можно здесь. А если вам интересно как оно устроено или вы желаете вынести себе мозг, добро пожаловать сюда, сюда, сюда и сюда. Но я вас предупреждал! Однако, платой за защиту от ошибок, является ухудшение возможностей расширения. Так, что этот метод, условно, можно назвать компромиссным. Но я не исключаю, что в будущем возьму курс на написание утилиты, отвечающей за интроспекцию и генерацию кода!
GitHub
thunder/thirdparty/next/inc/core/macros.h at master · thunder-engine/thunder
Thunder Engine – Cross-platform 2D and 3D game engine with modular architecture - thunder-engine/thunder
🔥2🥰1
Немного переделал систему управления стейт машиной рендеринга. Если вы не в курсе, помимо шейдера у пайплайна рендеринга есть и неуправляемые из шейдера части. Однако их можно дополнительно настраивать. Мне давно не нравилось как у меня сделана эта часть в OpenGL (кстати очень неудобная часть т.к. требует множество вызовов). В Vulkan все немного удобней. Эти изменения будут прокинуты в систему материалов и доступны для редактирования пользователями. Еще один шажок к большей гибкости!
🔥1🥰1🤯1
👻1