Хабрахабр

[Перевод] Автор Dwarf Fortress Тарн Адамс рассказывает о разработке игры

image

Одним из лучших способов применения мощных процессоров для развлечений долгое время была Dwarf Fortress — игра, в которой весь мир состоит из символов ASCII, и которая с радостью съест гигабайт памяти и большую долю процессорного времени.

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

Говорят, что это вызвано вашими грядущими тратами на лечение. Автор игры Тарн Адамс согласился ответить на наши вопросы о своём творении, которое, несмотря на существование множества имитаций, до сих пор остаётся совершенно уникальной игрой.
Gamasutra: мы слышали, что Dwarf Fortress выходит в Steam и itch.io в платной версии с упрощённым интерфейсом. Сложно ли оставаться на плаву инди-разработчику?

И иногда ты сталкиваешься с проблемами, с которыми не можешь справиться. Адамс: Да, много усилий приходится прикладывать, чтобы не уходить из бизнеса, и почти все разработчики вынуждены выдумывать творческие способы, чтобы иметь возможность оплачивать аренду жилья и прочие первостепенные нужды. Нам пока везло, но со временем приходится меняться: увольняться и устраиваться на другое место работы, переходить на Patreon, а теперь и в Steam с itch, или рисовать карандашные рисунки, что очень далеко от создания видеоигр.

Какие языки вы используете? Как выглядит ваша повседневная работа по созданию кода для Dwarf Fortress? Какие IDE, если пользуетесь ими? Какие библиотеки? На каком компьютере вы разрабатываете игру?

Пишу код на ужасной смеси C/C++ в MSVC Community. Я работаю на обычном, ничем не примечательном ноутбуке Toshiba с Windows 10. Больше ничем другим в Windows я не пользуюсь, за исключением части заголовков из MSVC (и до него), которые я использую уже десятки лет. Для legacy-версии я пользуюсь OpenGL, для основной — SDL, а для звука использую FMod. Я не совсем в курсе, что происходит в версиях для Linux/Mac, потому что не разрабатываю их на регулярной основе.

Dwarf Fortress разрабатывается уже почти 17 лет, и её кодовая база должно быть достигла гигантских размеров. На моей машине для создания мира при стандартных настройках требуется больше 1,2 гигабайта ОЗУ. Проблема таких мегапроектов заключается в том, что они становятся слишком большими и не помещаются целиком в мозгу. Какими стратегиями вы пользуетесь, чтобы проект оставался доходчивым и понимаемым для работы?

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

Мне до сих пор кажется, что это вдохновляющий способ работы. Я помню, что Threetoe (партнёр Тарна в разработке игры) пишет истории, а вы потом пытаетесь создать игровой движок, в котором они могут произойти. Бывало ли так, что сюжет одной из них полностью повторялся в игре? Были ли истории, которые вы отклонили, как слишком сложные в реализации?

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

44) показывает, насколько далеко вы от завершения (то есть на 44%). В Википедии написано, что номер версии игры (сейчас это . Есть ли у вас предчувствия о том, что произойдёт? Что ждёт Dwarf Fortress в дальнейшем? Какие серьёзные аспекты вам осталось реализовать?

Он должен быть довольно любопытным. Я завершаю релиз со злодеями, который выйдет в ближайшие несколько месяцев. Потом мы улучшим процесс осад и выполним ещё кое-какую работу, и после этого перейдём к Big Wait. Затем мы реализуем графику и повысим удобство игры для версий в Steam/itch. Она позволит нам генерировать мифы о творении и создавать полностью процедурные системы магии, а также открывать несколько окон обзора разных частей мира, и т.д. Это крупнейшая реструктуризация и расширение за всю историю DF. Потом будет релиз с собственностью/законами/таможней. Это будет отличное дополнение. Нам ещё многое предстоит сделать!  Мы даже не прошли ещё полпути до версии 1. После этого порядок пока не определён, но мы будем работать над экономикой, кораблями и другими важными компонентами, которых пока нет. А ведь версией 1. 0. 0 разработка игры на самом деле не закончится… возможно, к моменту её выпуска у нас просто останется не так много времени.

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

Частично это вызвано тем, что когда играешь, сложно держать все правила в голове. Да такое происходит постоянно! Хорошие истории можно найти на форумах, у стримеров, и так далее. Однако все мои запоминающиеся истории — это баги, потому что я редко имею возможность достаточно долго играть в игру, поэтому с точки зрения самостоятельно возникающего геймплея они мало интересны (даже если удивляют меня).

Граница между «микро» и «макро»: почему вы сделали её именно такой, между тем, что гномы могут делать сами, и что игрок приказывает крепости?

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

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

Какие шаги выполняет программа при построении мира?

Затем она выбирает, какой полюс у неё будет (например, север, юг) (или учитывает параметры, переданные игроком). Она выделяет память для карты. От полюсов зависит изменение температуры, и программа выбирает точки для высочайших пиков. Seed генератора случайных чисел задаёт базовые значения полей карты (высота, осадки, температура, водоотвод, вулканическая активность, дикая природа) для сетки переменного размера с учётом различных параметров (океанов, размеров островов, другой вариативности), а затем программа фрактально заполняет их. На этом этапе, если мир нельзя исправить, он отбрасывается, и всё начинается заново. Здесь она делает первый проход, чтобы посмотреть, как выполняется процесс, и пытается изменить высоты, чтобы карта укладывалась в желательные параметры.

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

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

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

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

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

Какие преимущества даёт подобная система? В DF мне больше всего нравится то, что игра не содержит никакой явной системы хитпоинтов, всё связанное с силой и уроном персонажа является частью сложной модели частей тела. Если кто-то решит создать нечто подобное, то какие препятствия его могут ожидать?

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

Как выглядит основной цикл игры?

Он начинается с проверки объявлений и считывания автосохранений, и т.п. Возьмём для примера режим гномов. Например, через каждую сотню тактов программа проверяет назначенные задачи и «странные настроения». БОльшая часть остального цикла происходит не в каждом такте. Через каждую сотню тактов программа обрабатывает выдаваемые гномам задачи. Армии перемещаются по карте мира. Каждые десять тактов меняются времена года, что влияет на погоду и карту (и локально, и во всём мире), а также выполняется проверка развития элементов сюжета (дипломаты, осады и т.д.) и проверка того, что форт всё ещё жив. Это своего рода невидимый аукцион, который используется для управления разными конфликтующими приоритетами.

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

Мёртвые гномы «думают» о своих ритуалах погребения, чтобы можно было назначить другим эти задачи. Если флаг задан, то раненые/испытывающие жажду/голодные гномы, которые не могут позаботиться о себе, получают обновление. Заключённые в клетки и цепи существа периодически обновляют свои мысли и ситуацию.

Затем, если существа пересекли края карты, они с неё убираются.

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

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

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

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

Наконец, обновляется камера, следующая за существом, за которым наблюдает игрок.

Я заметил, что существует множество способов отрисовки тайлов, и это зависит от того, что делает или как себя чувствует существо, сколько элементов на тайле, есть ли что-нибудь над ним, является ли тайл текущей водой или он погребён под камнем. В Dwarf Fortress для отображения мира используется тайловая карта на основе сетки — простой и эффективный способ представления. Как вы оптимизировали этот процесс? Когда DF принимает решение о том, как нужно отображать тайл, то что она делает?

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

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть