Подробнее о разработке движка для ролевой игры Knights of Frontier Valley

Подробнее о разработке движка для ролевой игры Knights of Frontier Valley.

Разработчик ролевой игры Knights of Frontier Valley рассказал о причинах создания собственного движка, его разработке, основных компонентах и управлении неигровыми персонажами в игре.

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

Всё это (и не только) работает благодаря собственному, разработанному специально для Knights of Frontier Valley движку. В примерах выше время захода солнца управляется «Менеджером времени» — компонентом, отвечающим за течение времени в игровом мире и освещение окружения. Осадки и качающиеся на ветру деревья возможны благодаря «Менеджеру погоды», а снежинки отрисовываются рендерером карты с использованием системы частиц. Передвижение персонажей по карте осуществляется по специально разработанному алгоритму поиска пути.

Сегодня я расскажу, как работают некоторые из этих механик, и зачем для этого понадобился собственный движок. Или посмотрите видео:

[Knights of Frontier Valley] На скриншоте: Погодные эффекты.
Закат солнца в Долине.

Мотивация

Начнём с вопроса «Зачем». Создание игрового движка с нуля для такой игры — амбициозное начинание. Возможности движка включают отрисовку изометрического вида (2.5D), продвинутое управление памятью, процедурную генерацию различных типов карт, обработку сложного поведения персонажей и их взаимодействий, сохранение состояния игры (для последующей загрузки), пошаговые механики и в реальном времени, собственный алгоритм поиска пути и многое другое. Такого объёма работ хватит на несколько лет.

Так зачем всё это, если есть много готовых движков, а некоторые ещё и бесплатны? Всё дело в поставленных целях.

Когда я начал работать над игрой в 2016 году, то вдохновлялся первопроходцами индустрии, такими как Ричард Гэрриот, Сид Мейер и Питер Молиньё, разработавшими первые игры в золотой век RPG в 80-х и 90-х годах. Тогда они не использовали сторонние движки, и на мой взгляд пройти по их стопам означало написать игру с нуля. Мне не нравилась идея делать игру на основе чужого, не до конца понятного мне кода, который я не смогу полностью адаптировать под свои задачи. Кроме того, я подумал, что это весьма увлекательно (и в целом так и есть).

Хотя Knights of Frontier Valley — мой первый игровой проект, за плечами у меня двадцатилетняя карьера в разработке ПО для настольных компьютеров, интернет-сайтов, встраиваемых систем и мобильных устройств. В Кремниевой долине я занимался программами для работы с GPS, разрабатывал софт под первые iPhone и оригинальный iPad, а также информационно-развлекательные системы и автопилот для Tesla.

Итак, программировать я умею, но разработка игр — совершенно другое направление, и мне предстояло многому научиться. Я начал делать игру, вкалывая на основной работе, поэтому занимался этим лишь по вечерам и в выходные. Примерно через три месяца у меня появился прототип с основным игровым циклом, где персонаж мог ходить по карте и выполнять простейшие действия. Прототип работал, но я понял, что с таким подходом никогда не создам игру с интересной визуальной составляющей. Используемые технологии попросту не подходили для игровой разработки, поэтому я всё бросил и начал заново — используя libGDX, упрощающий рендеринг OpenGL и некоторые другие игровые функции открытый Java-фреймворк. Я выбрал Java и OpenGL, поскольку хорошо знал язык, а ещё эти технологии использовались в успешных играх вроде Minecraft и RuneScape.

Отныне я был на правильном пути, и последующие годы развивал как саму игру, так и её движок.

[Knights of Frontier Valley] Карта мира.
Карта мира: текущая версия и ранние прототипы.

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

Основы движка

Но что такое «игровой движок»? Смотря кого спрашивать, но я считаю движком всё не связанное с логикой и внешним видом конкретной игры программное обеспечение. Это выделенная отдельно базовая функциональность, которую можно использовать и в других играх похожего типа.

Основы проектирования программного обеспечения: во-первых, чтобы код был читаемым, поддерживаемым и пригодным для многократного использования, функциональность должна быть инкапсулирована. Это означает, что отдельные части кодовой базы не должны содержать логику для разных функций. И во-вторых, поведение и визуализация всегда должны быть разделены.

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

Основной цикл — это выполняемая несколько раз в секунду функция. На каждом проходе обновляется весь игровой мир, и на экране отрисовывается отображающий актуальное его состояние кадр. В идеале основной цикл должен выполняться минимум 60 раз в секунду (= 60 FPS), чего достаточно для старых мониторов с соответствующей частотой обновления изображения (= 60 Герц). Сегодня это число зачастую выше, обычно 144 Гц.

Если ваша система недостаточно мощна для 60 FPS (узким местом обычно является GPU), можно заметить задержки и прерывистую анимацию. Но с Knights of Frontier Valley волноваться о видеокарте не придётся: графика в основном предварительно отрендерена, так что GPU может «пойти отдохнуть». Я не вижу тормозов даже на своё старом ноуте со встроенной графикой.

Мой движок состоит из:

  • Основной цикл
  • Конечный автомат
  • Управление памятью
  • Обработчик сохранений
  • Рендереры для карты и объектов
  • Систему воспроизведения видео
  • Вывод звука
  • Обработку ввода мыши/клавиатуры
  • Сетевые функции
  • Управление игровым временем
  • Поиск пути
  • Моделирование карт
  • Моделирование погоды
  • Моделирование персонажей и очередей действий
  • Моделирование перемещения персонажей

Не входит в движок:

  • Всё связанное с сюжетом и квестами
  • Графические ресурсы, музыка и звуковые эффекты
  • Пользовательский интерфейс
  • Логика процедурного построения карт
  • Специфичные для игры персонажи, объекты и предметы
  • Поведение NPC
  • Специфика конкретной игры, в том числе создание персонажа, боевая механика, спецэффекты (например, магия), пользовательские шейдеры, мини-игры и многое другое

О двух модулях я расскажу подробнее: моделировании персонажей (и связанных с ним очередях действий) и компоненте управления перемещениями NPC. Дополнительные подробности — в дневниках разработки о поиске пути и рендеринге на сайте проекта.

Моделирование персонажей и очереди действий

Моделирование персонажей — это программный контейнер, хранящий всех персонажей, которым могут понадобиться действия — для обновления поведения их следует сначала загрузить в память. Это относится ко всем NPC на карте с игровым персонажем, а также к некоторым другим, которым может потребоваться действовать по иным причинам: лидерам фракций, путешествующим (об этом позже) и важным квестовым персонажам. Когда игровой персонаж находится в городе, модуль обрабатывает сотни NPC — одни находятся в зданиях, а другие прогуливаются снаружи.

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

Когда игровой персонаж перемещается на другую карту, модуль определяет, каких персонажей в неё добавить (а каких — исключить), и выполняет необходимые действия. Вновь добавленные персонажи проходят оценку последнего сохранённого состояния — если их положение и деятельность больше не соответствуют их текущему поведенческому циклу (работа, сон, досуг и так далее), их телепортирует в нужное место на карте и они приступят к соответствующей деятельности.

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

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

[Knights of Frontier Valley] Список персонажей.
Список персонажей на текущей карте города вне зданий в режиме разработчика.

Теперь, когда вы знаете, какие персонажи хранятся в модуле и способны действовать, давайте рассмотрим, что означает «действие» в контексте движка.

У каждого персонажа есть «очередь» — список действий, которые он выполнит по порядку. В них входят «движение по траектории», «взаимодействие с объектом», «разговор», «атаку», «исполнение музыки», «чтение свитка» и так далее, а иногда это просто «ожидание». Когда персонаж не занят выполнением действия, из очереди берётся верхнее действие и запускается. Только если очередь пуста, персонаж действительно бездействует.

Очередь может содержать множество действий, и в начале их выполнения некоторые могут разделяться на несколько новых. Это сложная система, где каждое возможное действие персонажа необходимо задать заранее и оценить время исполнения. Сейчас существует 36 типов действий, и некоторые представляют собой наборы нескольких поддействий. Одно из них называется «пользовательское действие» и может быть настроено как угодно, что даёт безграничные возможности.

Если во время выполнения NPC своей очереди происходит что-то непредвиденное (например, атак игрока), очередь очищается, а поведение пересматривается: в качестве ответной реакции создаются новые действия. Когда игра сохраняется, очереди действий также сохраняются и восстанавливаются при загрузке, так что все персонажи продолжают прямо с того места, где и остановились.

[Knights of Frontier Valley] Список действий.
В режиме разработчика очередь действий персонажа можно вывести на экран. В этом примере игровой персонаж подойдёт к знатной даме, повернётся к ней, после чего остановит движение, и наконец вступит с ней во взаимодействие типа «Общение».

Модуль перемещения персонажей

При моделировании NPC персонажи могут перемещаться в реальном времени в любое место, даже через не загруженные в память карты. «Модуль перемещения» чётко определяет необходимые для путешествия действия и помещает их в очередь лидера группы. Например, для перемещения с чердака дома в подвал другого дома в другом городе потребуется выполнить следующие действия:

  • Запустить соответствующую анимацию движения (ходьба, бег или полёт... в других сценариях, возможно, также верховая езда или плавание)
  • Подойти к лестнице вниз
  • Спуститься по лестнице до входного уровня здания
  • Подойти к входной двери
  • Взаимодействовать с дверью для выхода из здания
  • Подойти к точке выхода из города
  • Покинуть город
  • Идти по миру ко входу в город назначения
  • Войти в город
  • Пройти требуемые городские кварталы и добраться до нужного дома
  • Подойти ко входу в дом
  • Взаимодействовать с дверью для входа в здание
  • Спуститься по лестнице в подвал
  • Дойти до точки назначения в подвале

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

Путешествующие NPC остаются в модели персонажей, даже если покидают карту с игроком, ведь им необходимо действовать вплоть до пункта назначения. Пока персонаж находится на одной с игроком карте, все препятствия на его пути известны и загружены в память, и их можно обойти с помощью компонента поиска пути. Но если персонаж ушёл на другую карту, как система узнаёт варианты обхода препятствий и определит временные затраты, если эта карта не находится в памяти?

Я решил эту проблему, добавив концепцию «маршрутизации вне карты» — систему, использующую среднее время пути при перемещении на определённое расстояние по различным типам карт. Проложив огромное количество маршрутов на каждом типе карты, я вычислил среднее время их прохождения. Это означает, что если NPC покинет карту с игроком и исчезнет из виду, а игрок позднее последует за ним, он найдёт NPC именно в том месте, где тот должен находиться.

Это не реальный расчёт, а приближение и своего рода «подделка» части путешествия. Но она отлично работает, и игроки никогда не узнают, что части маршрута не обсчитывались в реальном времени, МУАХАХАХАХА. Ладно, ну, ВЫ теперь знаете об этом — считайте это наградой за чтение до конца. Ваша способность удерживать внимание достойна восхищения, и у вас, вероятно, есть всё необходимое для написания собственного движка.

CC0
Вы можете копировать, изменять, распространять и исполнять данное произведение, даже в коммерческих целях, не спрашивая разрешения.

Поиск по сайту

Случайное из галереи

Возможность повоевать с демонами на их территории.
Возможность повоевать с демонами на их территории.

Сообщения на форуме | новые

Помогите найти моды для Baldur's Gate 3 (не читерные). на форуме Baldur's Gate III.
Последнее сообщение оставил Mercutio (2025-09-17 в 23:29). Ответов: 13.
Baldur’s Gate: Siege of Dragonspear на форуме Baldur’s Gate.
Последнее сообщение оставил TimeusGaylord (2025-09-17 в 22:57). Ответов: 138.
[В разработке] Vampire: The Masquerade — Bloodlines 2 на форуме Всё остальное.
Последнее сообщение оставил Хоттабыч (2025-09-17 в 21:21). Ответов: 167.
Malevilent на форуме Ролевые боевики.
Последнее сообщение оставил Dazdraperm (2025-09-17 в 15:55). Ответов: 6.
Проверь себя. Викторина на выходные. на форуме Оффтопик — Разное.
Последнее сообщение оставил Dazdraperm (2025-09-17 в 15:40). Ответов: 1407.
[В разработке] Underrail: Infusion на форуме Всё остальное | Инди.
Последнее сообщение оставил QweSteR (2025-09-17 в 11:18). Ответов: 62.
Бордель услаждения интеллектуальных страстей — 2 на форуме Оффтопик — Разное.
Последнее сообщение оставил Хоттабыч (2025-09-17 в 09:18). Ответов: 1508.
Общее обсуждение харда и софта на форуме Hard-n-Soft.
Последнее сообщение оставил silmor_senedlen (2025-09-16 в 13:06). Ответов: 3595.
Tainted Grail на форуме Бродилки по подземельям.
Последнее сообщение оставил darer333 (2025-09-16 в 11:33). Ответов: 35.
Avowed на форуме Avowed.
Последнее сообщение оставил Bellerogrim (2025-09-16 в 09:48). Ответов: 158.

Ожидаемое | таблица

Новости C.O.R.E.

Статьи C.O.R.E.

Случайная цитата

M'aiq carries two weapons, to be safe. What if one breaks? That would be most unlucky.

M'aiq the Liar, The Elder Scrolls V: Skyrim

Оставьте свой отзыв: QR-код для отзывов в «Яндексе».