Разработка 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

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

94
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