Разработка 2D Fantasy Kingdom Sim с нуля. Часть 1: Язык, Движок, Редактор и Графический API

Небольшое введение, задачи прототипа, и разбор технологий которые мне видятся актуальными на 2022 год для основы 2D игры, если вы по каким-то причинам решили не использовать Unity, Unreal или Godot.

LDTK (фото с сайта)

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

В своем первом посте на DTF пару дней назад я задал вопрос стоит ли здесь делиться подробностями разработки прототипа 2D симулятора в духе RimWorld и Majesty. Поскольку мой пост с одним лишь обрезанным скриншотом из прототипа и редактором кода набрал 30+ лайков, то я решил что это явный успех и принялся за написание статей. Иметь хоть и небольшую, на преданную аудиторию для вопросов, обмена опытом, и обратной связи на данном этапе это предел моих мечтаний 🙂

Обо мне и краткая предыстория

Мне 31 год и последние 10 лет я живу в США, сначала в ЛА и Сан Франциско, а в последние 2 года перебрался в Остин в Техасе. По своей основной специальности я программист и математик. Еще я в детстве 10 лет ходил в художественную школу и последние 6 лет занимался съемкой и цвето-кором в качестве хоби, так что есть некоторые навыки не только в техническом направлении. Тем не менее, после учебы я 8 лет проработал в нескольких FANG компаниях и мой основной опыт это программирование нагруженных бекендов и немного ML и роботов. В основном это примерно поровну Go, C++ и Rust. И немного Typescript и Python для интерфейсов и ML.

Хотя многие вещи из моего прошлого, особенно в robotics применимы в играх, собственно, в геймдеве у меня нет нормального опыта. Поэтому обратная связь это одна из причин почему я задумался начать писать на DTF. Играми я интересуюсь давно, еще в 16 лет в физмат лицее программировал поиск пути и простенькие 2d игры, но фуллтайм этим никогда не занимался. До этого момента я несколько раз пробовал писать свою игру в свободное, сначала на голом C++ и Vulkan, потом со своим знакомым на Unity, но как-то эти попытки затухали через несколько месяцев. В этот раз я решил взять что-то не настолько низкоуровневое как чистый Vulkan, и не настолько высокоуровневое как Unity и попробовать заново.

Концепция и задачи прототипа

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

Majesty и RimWorld – идейное вдохновление.

-SNG

С технической точки зрения, прототип должен уметь делать следующее:

  • Загружать мир, сущности и ассеты из файловой системы.
  • Уметь рисовать спрайты, gizmos, поддерживать слои, 2D меши.
  • 2D анимации через спрайты.
  • Камера с ортографической проекцией, возможность менять масштаб.
  • Уметь обрабатывать сотни сущностей, и взаимодействий: 1) Герои, фауна, монстры. 2) Собираемые ресурсы. 3) Динамические структуры –постройки, мебель, предметы мира. 4) Здоровье. 5) Подбираемые предметы. 6) Стеки и хранилища предметов. 7) Инвентарь героев. 8) Простая система прокачки – опыт и скиллы. 8) Экономика.
  • Состояние сущностей – отдыхает, бодрствует, идет к цели и пр.
  • Игровой AI который понимает цепочки подзадач для выполнения целей, может симулировать простые решения и взаимодействия. Собственно это один из основных фокусов игры. То, что, как по мне, сложнее всего концептуализировать и то что должно быть сделано наиболее интересным способом для развития игры: 1) Сбор и обработка ресурсов. 2) Строительство. 3) Ремесло. 4) Простая система квестов для героев. Квесты будут раздавать не-герои поселения, например – собери 10 ресурсов для кузница. 5) Ближний бой. 6) Система выживания – героям нужно что-то есть и отдыхать. 7) Базовая торговля – герои должны покупать предметы и оружие, платить за жилье и еду. 8) Поведение монстров и фауны.
  • Свойства проходимости ландшафта, навигация, динамические препятствия. Много разных поисков пути. Как на карте, так и в пространстве задач.
  • 2D коллизии.
  • Календарь, смена дня и ночи.
  • Базовое аудио.
  • 2D интерфейс: окна, меню, drag & drop, hotkeys, рендер текста, выделение сущностей, задание целей, инвентарь и карточка сущностей (аватар, описание, состояние, статы), меню строительства, счетчики ресурсов экономики.
  • Туман войны.
  • Найм героев за ресурсы.

Что бы хотелось еще, но этого скорее всего не будет в прототипе в 2022.

  • 2D материалы, эффекты, тени и освещение, системы частиц.
  • Водные пространства.
  • События мира.
  • Процедурная генерации мира. Может только самая базовая для автоматизации.
  • Подземелья.
  • Мультиплеера, но я буду держать его в уме и добавлю при первой возможности.
  • Сюжет, диалоги, сценарии, сюжетные предметы, квесты, локации и персонажи. В прототипе только песочница с симуляцией.
  • Магия и дальный бой.
  • Симуляция социальных связей.
  • Фракции. Пока что только один игрок.
  • Биомы и бесконечный мир.
  • Поддержки чего то кроме PC и Mac.
  • Модификаторы и сложная система здоровья (повреждение частей тела и пр.).
  • Партии и гильдии.
  • Симуляция погоды.
  • Нечеткое принятие решений через нейронные сети. Есть идея сделать что-то в духе идеи из Black & White 2 2006 года, где существа принимали решения через запрос к нейронной сети, без жестко прописанных правил. По сути игра должна генерировать набор всех решений для персонажей, а NN модель должна их ранжировать и выбирать наиболее подходящее исходя из состояния героя и его статов (собирать ресурсы, есть, спать, убегать от монстров, заниматься разведкой и пр.). Цель для NN может быть разной исходя из класса героя, условно для лучника это может быть разведать как можно больше окрестностей и не умереть, для паладина – убить самого опасного монстра рискуя собой. Если прототип с основной механикой будет готов к ноябрю, то это одна из основных идей которые я хочу попробовать используя gym от OpenAI.

Выбор технологий

Движок. В моем случае, изначально у меня не было процесса где я сидел и думал какая технологическая основа подойдет для реализации. У меня был опыт с Unity и низкоуровневыми графическими интерфейсами, но я все не решался начинать делать на этом игру. В какой-то момент я наткнулся на Bevy, изучил как работает ECS и иерархия сцены и у меня понемногу начали вырисовываться идеи как можно это все использовать. Bevy мне показался довольно простым и понятным эдаким набором деталей Лего из которых можно собрать что угодно. Легковесный, гибкий, не слишком навязывающий свой подход и имеющий достаточно низкую связанность компонентов. При этом нативный и довольно производительный. Хотя производительность пока для прототипа так важна. К тому же я уже давно хотел поработать над чем-то таким на расте. Поскольку игра в 2D, то и большинство фичей больших движков мне казались не сильно нужны. Хотя в Bevy есть, насколько я могу судить, довольно грамотно спроектированный Render Graph, GLTF, PBR. У движка есть примерно 3k пользователей на Reddit и примерно такой же онлайн в Дискорде. Из спонсоров имеется Embark, вполне серьезная студия из бывших авторов серии Battlefield (как я понял из их сайта, они довольно активно используют Rust в новых проектах). Bevy можно скомпилировать под Mac, Windows, Linux, iOS и Android. Здесь можно почитать про поддержку консолей. Из плюсов, для Bevy уже написано несколько хороших плагинов для интеграции физики, инспектора сцены, UI, конечных автоматов и прочего.

Также, Bevy может компилироваться в WASM, поэтому простенькие примеры можно запускать прямо в браузере поддерживающем WebGPU или WebGL:

Пример с рендерингом GLTF модели работающий в браузере.

Графический API. Следущий переломный момент для меня наступил когда я посмотрел лекцию по WGPU. Тогда я понял что это именно те инструменты которые я искал и начал эксперименты. До этого у меня было представление что WebGPU это стандарт для веба. Оказывается это не совсем так. Несколько лет назад стандарт задумывался разработчиками браузеров именно как низкоуровневая альтернатива WebGL. Насколько я понял над WebGPU работают именно разработчики браузеров, и он никак не связан с Kronos. Изначально, библиотека WGPU создавалась для реализации стандарта WebGPU в FireFox, но позже Mozilla и Google стали поставлять свои реализации этого стандарта для нативных языков отдельно от браузера. У Google свой аналог WGPU называющийся Dawn, и в целом устроенный похожим образом, но реализованный на C++. По сути WGPU это очень тонкая низкоуровневая надстройка над графическими API вроде Vulkan, Metal и DX12 написаная на Расте с заголовками под Си. Вам дается есть очень явный доступ к графическим девайсам – очереди, пулы, буферы команд, дескрипторы, графические и вычислительные пайплайны, примитивы для синхронизации и вот это все. По сложности WGPU где-то посередине между Metal и DX12. Это почти 1-в-1 копия подхода низкоуровневых графических API, из отличий в нем упрощена работа с памятью, и требуется немного меньше кода. Главный плюс WGPU по это кроссплатформенность. В зависимости от системы (mac, pc, ios, android) можно указать разный backend – Vulkan, dx12 или metal. В расте многие библиотеки, в том числе bevy, поддерживают вывод через WGPU, поэтому их ресурсы можно переиспользовать как аттачменты в одном пайплайне без трансфера через CPU.

Veloren – кросс-платформенная игра, где вывод графики сделан через WGPU.
Veloren – кросс-платформенная игра, где вывод графики сделан через WGPU.

В WGPU пока нет фичей последних поколений графических ускорителей типа умного апкскейла, ускорения рейтрейсинга и прямой загрузки ресурсов из файловой системы в память память графического ускорителя. В качестве языка шейдеров можно использовать WGSL или GLSL которые будут транслироваться в SPRIV или MSL в зависимости от системы. Насколько я понял, главный разработчик WGPU до этого работал над графическим пайплайном в RDR2. Также автор WGPU довольно активно контрибьютил в Bevy.

Производительность / субъективная простота использования графических API.
Производительность / субъективная простота использования графических API.

Редактор мира. Следующий этап был поиск редактора мира чтобы не приходилось работать над картой через редактирование текста. Поскольку в Bevy редактор пока находится на стадии обсуждений, то пришлось искать что-то на стороне. Насколько я понял для 2D игр есть два популярных варианта – Tiled и LDTK (разработчик – студия работавшая над Dead Cells). Я выбрал последний, для моих задач его должно в основном хватать, но в целом они довольно похожи. Идея в том что вы загружаете в редактор свои тайлсеты, создаете из них карту с помощью сеток с разными слоями и затем добавляете сущности на этой карте. Для сущностей можно указывать свои кастомные свойства – примитивы (числа, строки, массивы), другие сущности, места и пути на карте и прочее. После этого карту можно импортировать в JSON файл и загрузить в свою игру. Для Раста уже написан свой парсер LDTK. Добавить парсер в ассет менеджер Bevy заняло примерно 30 минут. Распарсенный файл LDTK затем указывается как ресурс в системе которая собирает мир игры на старте. Эта система обходит ресурс LDTK, слой за слоем собирает карту из спрайтов, просчитывает данные для навигации и спавнит сущности с заданными параметрами. В целом LDTK в Bevy пока что оставляет приятные впечатления.

Редактирование сущности в LDTK (фото с сайта).

Для автоматизации в LDTK можно создать свои правила как которые будут выбирать нужные тайлы для точек соприкосновения разных поверхностей. Из минусов – пока что нет какой-то явной поддержки анимаций.

Язык программирования. Думаю будет не лишним упомянуть язык Rust. Язык в целом очень похож на последние итерации C++, особенно в семантике. В расте нет явной поддержки ООП, в этом он в чем по похож на Go, только вместо интерфейсов здесь типажи. Из главных отличий от других языков – borrow-checker который помогает не допускать некорректного доступа к общим ресурсам, и в основном предотвращает многие классы ошибок памяти и много-поточности. Если отбросить субъективные аспекты (которые по-моему крайне важны если вы – соло-разработчик), то Раст сопоставим с Си и Си++ по производительности (также rustc использует один бекэнд с clang – LLVM), добавляет в исполняемый файл минимум рантайма и не использует сборщик мусора. Для меня огромным плюсом также является cargo, в отличие от Си++ и Си, в Расте намного удобнее управлять зависимостями проекта. Также в отличие от Си и Си++ для раста есть только одна реализация и один компилятор под все платформы что облегчает портирование. На этом сайте собраны библиотеки на Расте которые могут быть полезны при разработки игр: arewegameyet. rs.

Собственно на этих четырех технологиях я начал разработку проекта несколько месяцев назад. Думаю на этом пока закончить первую статью. Если будет достаточный интерес к таким материалам, на следующей неделе я напишу про базовый сетап для Bevy и то как устроена загрузка мира из LDTK, ресурсы и ECS. План на следующие несколько месяцев примерно такой:

  • Возможности Bevy, LDTK и загрузка ресурсов и ECS.
  • 2D Пайплайн, шейдеры, отладка шейдеров, и спрайты.
  • Навигация и поиск пути на карте.
  • Взаимодействия сущностей через ECS, сбор ресурсов, цепочки задач.

Буду рад обратной связи. Дайте знать насколько глубоко нужно раскрывать тему. Больше или наоборот меньше технических деталей? Спасибо!

-SNG

Вторая часть здесь:

9494
30 комментариев

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

Несколько заметок по поводу затеи в целом:

- Ментальность. Специалисту трудно выйти из зоны комфорта, когда нужно решать управленческие задачи. Когда в руках привычный молоток - видишь вокруг только гвозди. Программировать - привычно, понятно и интересно. А делать интересную игру - непонятно, непривычно и страшно (вдруг идея окажется неинтересной). В итоге, спустя месяцы выясняется, что лестница, на которую с таким энтузиазмом забирались, была приставлена не к той стене и получается, в лучшем случае, технологическая демка, но не игра. Outer Colony, как пример.

- Определиться с целью: хобби или коммерческая разработка. Если планируете выпустить демо в обозримом будущем и в перспективе - зарабатывать, то примеряйте на себя роль гейм-дизайнера \ продюсера в первую очередь.

- Начинать с геймплея. Почитайте про MDA framework, это задаст правильный настрой. Игроку важен игровой опыт (aesthetics в MDA), а технологии - это лишь инструменты для его создания. То, что вы перечислили - это пока набор механик, без привязки к опыту. Лично я так и не понял из двух статей: 1) в чем именно будет геймплей игры, 2) чем он будет значительно лучше референсов. На кладбище игр полно проектов с эпитафией "хотели сделать как референс". Например, Super Combat Fighter.

- Планы на демку - слишком оптимистичные, на полную версию - нереалистичные. По демке - если у вас по каждой задаче расписаны детали, вплоть до структур данных, алгоритмов и формул, то мб успеете к ноябрю впритык. По полной версии - fuzzy logic, NN - это возведение времени разработки в квадрат. Мультиплеер - в куб. Напрмер, в Project Zomboid два выделенных чувака (+аутсорсеры с недавнего времени) пилят вменяемый мультиплеер уже несколько лет и все не допилят.

Резюмируя, я бы рекомендовал вам переключиться в режим гейм-дизайнера, определить в чем будет геймплей, какой критичный функционал для него нужен (и вырезать все некритичное, например: анимацию, камеру, физику, аудио, меню), реализовать критичные механики максимально просто и быстро (в ущерб качеству \ технологиям, т.к. это прототип на выброс. Скажем, вместо GOAP - использовать FSM или decision tree на if'ках; вместо Astar сразу телепортировать в position) и выдать на растерзание толпе, чтобы проверить интересность идеи игры. А обратная связь от игроков уже подскажет, куда двигаться дальше.

13
Ответить
Автор

Очень полезные советы, спасибо!

2
Ответить

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

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

Мне эта тема тоже очень нравится, я в одном из своих учебных упражнений по Unity делал сцену на примитивах в которой герои, стражники, монстры и налоговые инспектора делают свои дела. Герои исследуют, защищают, атакуют цели под флагами монстры просто крашат вся. Баблишко капает герои покупают бутылки, кольца защиты новые пушки и броню. Было прикольно и без анимации и без моделей. Поиск пути писал примитивный свой без NavMesh даже работало кое как у меня. Сейчас опыта поднабрался планирую когда то вернуться к этой теме если получится, но не в этом году.

3
Ответить
Автор

Спасибо. Игра все же не прям совсем с нуля, и у меня есть надежда что выбранный уровень абстракции в моем случае даст больше продуктивности чем попытки адаптировать Unity или Godot под не совсем стандартный жанр (возможно я конечно не прав). Я только сейчас закончил работу над основными механиками и приступил к геймплею в прототипе. Следующие две-три статьи все же будут скорее техническими, но после этого я начну фокусироваться на публикции подробностей механик геймплея.

Как я уже писал в самом начале, в этих статьях я не ориентируюсь на широкую аудиторию, но за отзыв спасибо, постараюсь более интересно писать о технических деталях проекта.

3
Ответить

заумьВроде бы наоборот дружелюбно написал, как настроил себе тулсет и почему он именно такой.

1
Ответить

Очень интересно как разработчику, спасибо!

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

Что ещё хочу заметить: то, что ты называешь прототипом - это будет прототип движка игры, а не прототип самого геймплея. Это даже не прототип, а какой-то PoC. "Да, я сделал игру на расте и webgpu". А что за игра, в чем ее кайф - не понятно даже после этого прототипа, он не проверяет гипотезы, он просто является кодом-основой для самой игры. Ну будет какая то симуляция человечков, которые что-то делают - я лучше пойду в римворлд играть, она уже готова и она классная) ну ты понял.

Опять же, это просто первые мысли. Я люблю технологии и с удовольствием бы читал тонны текста только про одни шейдеры, например. Я не спорю, что идеи у тебя есть там крутые - но вот о них, наверно, важнее всего в первую очередь говорить. Статьи о том, как ты реализуешь эти идеи (с техническими подробностями) я бы завал с ещё большим удовольствием! Ты сам пишешь "концепция и задачи прототипа" - концепции нет, задач нет. Есть жанр, стек, чек-лист движка. Задача твоего прототипа - просто иметь в себе сделанные технические фичи. Это плохая задача. Есть опасность выгореть и забить, так и не начав пилить геймплейные вещи, имхо.

А так, круто! Жду инфы по геймплею и более структурированной нудятины про раст и низкоуровневые графические апи.

2
Ответить
Автор

Спасибо. Я это понимаю, отвечал на похожий комментарий в другом посте – думаю сначала статьи на более общие темы – ECS, графика, поиск пути и пр. То что нужно решить в первую очередь. Особенности геймплея это то над чем я постоянно экспериментирую в данный момент и планирую делать все больший фокус по мере готовности основных механик.

Я планирую об этом писать, но уже немного постфактум когда это будет готово и можно будет показывать результат.

Мне кажется симуляция и реализация мира где твои поселенцы дают квесты другим поселенцам это довольно необычно и добавляет глубины. Я начну об этом писать ближе к концу лета, надеюсь у меня будет интересные результаты к этому времени.

4
Ответить