Дерево в облаках
Процедурная генерация для рогаликов: Миллионы, миллионы, миллионы pixel shop!
Вы когда-нибудь играли в Daggerfall? В классические рогалики? В Dwarf Fortress? Вам было интересно, как именно создаются в них здания, города или даже миры? Если да, то этот цикл (надеюсь) статей для вас!
Я принимаю участие в разработке Python-библиотеки для процедурной генерации roguelike-карт. После моих первых принятых в основной код генераторов карт я решила записать видео- и текстовые туториалы, которые подробно объясняют процесс работы кода.
Давайте начнем!
Каждый магазин представляет собой прямоугольную карту из клеток. Длина и ширина здания лежит в определенных допустимых интервалах, поэтому до запуска генерации мы проверяем входные параметры длины/ширины и кидаем исключение, если они слишком маленькие или большие.
Благодаря исключениям ТАКОЕ не сгенерируется никогда.
После проверок размеров идет большой блок с проверками типов стен, полов и магазина. Стены могут быть деревянными, каменными или кирпичными. Полы, в свою очередь, могут быть из паркета, из камня или из грязи.
Тип магазина может быть следующим:
- С едой
- С драгоценностями
- С одеждой
- С оружием
- С броней
- С зельями
- С инструментами
- С магическими предметами
Если тип стены, пола или магазина не указан, то он выбирается случайным образом.
С полученными типами стен и пола генерируем большую пустую комнату, которая и будет нашим магазином. Создаем переменные, которые будут разделять магазин на торговый зал и жилую комнату с мини-складом. После чего вызываем функцию создания торгового зала и передаем в нее эти переменные как длину и ширину зала.
Как работает эта функция?
Создаем новую пустую комнату. Причем так как мы УЖЕ проверили весь магазин на корректность размеров и материалы, для этих комнат ничего проверять не надо. Расставляем на карте выход из магазина, масляную лампу, прилавок и кучку монет (эти объекты генерируются в каждом магазине). После этого определяем словарь, в котором мы выбираем для каждого типа магазина определенные типы предметов.
Что у нас будет на этот момент.
Далее немного магии:
Создаем список, который хранит в себе все координаты для предметов в определенной части магазина. Далее для каждого предмета мы запускаем бесконечный цикл. В нем мы случайно выбираем координату для него. Если этой координаты НЕТ в списке существующих, то мы:
- Кладем предмет в эту клетку
- Добавляем координату в список
- Выходим из цикла
Картинка для тех, кто понимает клингонский питонячий.
Зачем вообще такие сложности? Допустим нам надо разместить на площади в пять на пять клеток двадцать предметов. Если мы каждый раз будем случайно выбирать клетку и класть в нее предмет, то у нас будет две проблемы:
- Первая: будет много пустых клеток
- Вторая: будет много клеток с двумя, а то и более предметами.
Поэтому мы запоминаем все координаты всех предметов, и каждый раз выбираем случайную клетку до тех пор, пока не выберем пустую, после чего кладем в нее предмет. Правда этот код уйдет в бесконечный цикл, если предметов больше, чем свободных клеток. Но такой случай можно закрыть совмещением этих двух картинок:
Описанным выше алгоритмом мы создаем витрину с товарами около дальней стены торгового зала. Потом так же раскидываем по магазину еще несколько предметов и кошку и возвращаем из функции карту торгового зала, которую записываем в отдельную переменную.

Дальше мы вызываем функцию генерации жилой комнаты и мини-склада. Она работает практически так же, как и прошлая, так что ее можно описать и анимировать вкратце:
- Создаем комнату.
- Делим ее пополам.
- Создаем стены: теперь у нас две комнаты.
- Создаем двери.
- Расставляем по спальне кровать, факел и сундук.
- В зависимости от типа магазина, случайно раскидываем по складу определенные товары.
- И возвращаем карту.

Мы опять попадаем в главную функции генерации магазина. Вклеиваем в него СНАЧАЛА торговый зал, а потом склад со спальней. Почему важен порядок? Дверь из торгового зала в склад была создана на карте со складом, так что если вклеить сначала склад, а потом торговый зал, то дверь просто исчезнет. Дальше при желании мы можем создать экстерьер магазина и перевернуть здание. Это даст нам в пару раза больше разнообразия с минимальными усилиями.

Готово! Теперь у нас есть генератор средневековых или фэнтези магазинов, каждый из которых будет узнаваем, но при этом уникален. Примерно таким же образом создаются процедурно генерируемые здания в различных играх.
Ссылка на исходный код генератора: воть. Также можно быстро и в красивом виде посмотреть, какие именно видео генерируются, в этом видео:
А с вами была Мурмия, всем спасибо, всем пока!
Escape From Farm - игра в разработке
Всем привет!
Очень чешется поделиться новостью, которая важна в основном мне и пока небольшому сообществу. Надеюсь, что и среди пикабушников смогу найти неравнодушную публику.
В разработке шуточная выживалка-симулятор Escape From Farm (да да, называли по аналогии с Escape from Tarkov). Проект хоть и шуточный, но намерения у нашей неназванной игровой компашки довольно серьезные.
В этом посте я хотел бы рассказать немного о проекте и о целях, которые игра преследует.
Начну, пожалуй, с описания игры.
Escape From Farm - игра про корову, которой тебе предстоит управлять. Тебе нужно будет делать все то, что делают обычные коровы:
- Есть много растительности и управлять процессом пищеварения, чтобы изготовить молоко для требовательного фермера.
- Конкурировать с другими травоядными животными, ведь трава восполняется лишь усилиями самих животных.
- Бороться за выживание отбиваясь от хищных животных.
и многое другое.
Цель проста - сбежать всевозможными путями с фермы (почему все именно так объясняется в готовящейся катсцене для играбельной демки)
Игра подразумевает много динамичной процедурной растительности, где у каждого растения свои параметры и элементы, которые корове нужно будет искать для выполнения ежедневных обязательств перед фермером. Злить фермера невыполнением плана точно не стоит.
Углубляться дальше не станем, ведь что-то еще может поменяться.
Сам проект подразумевался как портфолио. Ну, типа мини игрушка, в которой есть все то, что я мог бы реализовать для заказчика. В итоге, задумка с коровой стала чуть серьезней в плане качества реализации и допускать кое-какие баги стало неприемлемым. Да и помощь в виде неравнодушных к проекту друзей подоспела.
Игра не претендует на окупаемость или какую-либо чрезмерную популярность и делается в целях прокачки и применения скиллов и возможности реализовать самые абсурдные идеи, которые хотели бы видеть в наших любимых играх.
Это был первый пост по проекту. Спасибо, что дочитали до конца!
Группа проекта, где больше обновлений по разработке почти каждый день: Escape From Farm
Как создавали процедурную разрушаемость в Control
На GDC Summer 2020 Йоханнес Рихтер, старший художник по VFX в Remedy, рассказал о том, как студия работала над разрушаемым окружением в Control. Мы выбрали из выступления главные тезисы.
Выступление пересказал: Артемий Леонов
Перед командой стояла цель создать окружение, при взгляде на которое игрок понимал бы, что он может взаимодействовать практически со всем, что видит, и что у этого взаимодействия будет постоянный и предсказуемый результат.
Для того, чтобы воплотить такую концепцию в жизнь, была необходима реалистичная физика объектов — но разработчиков сдерживали технические ограничения платформ, на которых должна была выходить Control, и небольшой размер команды. В итоге окружение должно доносить до игрока примерно такую мысль: «Развлекайся, уходи в отрыв, устраивай полный хаос на своём пути… но в рамках разумного, пожалуйста, иначе игра не справится».
При работе над эффектами Рихтер придерживался принципа «гранулярности»: все детали, которые образуются в процессе «разрушения», — отдельные объекты, их части, обломки и мелкие частицы, — должны были быть отражены визуально. По такому же принципу создают эффекты для кино: если какому-то из этих элементов не уделить достаточно внимания, правдоподобная картинка не сложится.
Элементы разделили на три накладывающихся друг на друга уровня. Первый реализован при помощи Rigid Body Simulations: это целые объекты и детали окружения, а также их отдельные части. Второй уровень (Mesh particles, material decals) — это мелкие обломки и осколки. Третий (Particle Sprites, Mesh particles) — искры, дым, мелкие частицы материалов.
Рабочий процесс выглядел так:
—Художник по окружению задаёт геометрию уровня, создаёт конкретные пропсы и модули.
—Специалисты по VFX занимаются ригами и анимацией.
—Всё это имплементируется в Northlight — собственном движке Remedy.
Разрушаемость решили сделать «процедурной»: иными словами, игра должна была сама обрабатывать и интерпретировать поступающую информацию об игровом мире на основе заданного набора правил.
Предположим, в игровом мире есть скамья. Разработчики сообщают игре, что её основа сделана из бетона, сиденья — из материи, а растения, которые на ней установлены, состоят из материала «растения». Теперь, когда у игры есть эта информация, разработчики могут создавать на её основе правила.
К примеру: если игрок стреляет в объект «растение», то от него отделяются кусочки листьев. Если выстрелить в бетонный объект, он расколется на несколько кусков и сгенерирует «пыль». В итоге движок «знает», из чего состоит любой объект в игре, и как этот материал реагирует на разные виды воздействия, совмещает эту информацию с данными о физическом поведении объектов — и на выходе получается та самая «процедурная разрушаемость».

Помимо стандартных Rigid Body объектов, в Control используются так называемые «куски» (chunks) — несколько небольших объектов, соединённых «связями» (bonds). У них общий коллайдер, и они ведут себя как один большой объект — до тех пор, пока не распадутся на части. Месторасположение соединений (joints), — то есть точки, по которым объект распадается, — также создаются процедурно.
Для каждого материала существует несколько уровней «разрушенности».
Один из «кусков», образующих составной объект, может быть полностью разрушен, — но это не будет автоматически означать, что соединение пропадёт. Например, часть двери может разлететься в щепки, но нетронутая часть останется на месте и будет открываться и закрываться, как полноценная дверь. При помощи этой системы Рихтер хотел избежать ситуации, при которой объекты немедленно полностью распадаются на части после любого взаимодействия, — как это бывает в некоторых играх с разрушаемым окружением.
Одной из главных задач VFX-команды стала оптимизация: без уловок обработка такого количества данных слишком нагружала бы систему. Поэтому разработчики ввели следующие правила:
— На экране одновременно могут присутствовать не более 200 активных Rigid Body. Объекты вне поля зрения игрока исчезают и не обрабатывается.
— Когда происходят «крупные события», в которых задействовано очень много объектов — например, взрыв, — коллизия задерживается на 10 кадров, чтобы дать системе время.
— Объекты очень быстро «засыпают» после того, как были приведены в движение. По словам Рихтера, это вполне реалистично. Если объект — не шарик-попрыгунчик, который уронили на пол, то он вряд ли будет долго двигаться после падения.
— Также разработчики активно использовали частицы (particles), — в том числе чтобы маскировать несовершенства системы. Они появляются в результате выстрела, при разрыве соединения между «кусками» и в случае полного разрушения объекта: они не просто исчезают, а превращаются в «пыль».
— Иногда, если на экране одновременно происходит слишком много событий, игра «пропускает» один или несколько уровней разрушения объектов. К примеру, в какой-то ситуации стол не перейдёт на второй уровень разрушения, а сразу рассыпется на частицы.

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

Инди платформер с ASCII-артом и процедурной генерацией
Всем привет. На днях я выпустил на андроид свою первую полноценную игру. Хочу немного рассказать о ней сообществу.
Unsigned Character - это платформер с минималистичной боевой системой и бесконечным генерируемым миром. Главный герой вооружён бластером с бесконечными патронами. По ходу игры ему предстоит сражаться с разнообразными противниками. Процедурная генерация и физика создают для игрока множество интересных ситуаций. Основной упор в геймплее делался именно на динамику боёв.


Для этого проекта я придумал и реализовал довольно сложный генератор уровней. При каждом запуске создаётся уникальная бесконечная пещера. Игра чем-то напоминает рогалик, но при этом остаётся честным платформером. Игрок не пользуется левитацией или какими-то другими средствами, чтобы сгладить косяки генерации.
Вся графика сделана с помощью ASCII-арта с парой оговорок. Во-первых, физические объекты перемещаются попиксельно, не привязываясь к символьной сетке. Во-вторых, я использую затенение заднего плана, чтобы активные объекты не сливались с ним.
Игра разрабатывается на Java с использованием фреймворка LibGDX. Проект собирается на ПК и андроид, однако выпуск на ПК не планирую. Версия для андроида есть в Google Play (бесплатно).
Ну и напоследок пара скриншотов. Буду рад отзывам!
Страница игры в Google Play: https://play.google.com/store/apps/details?id=com.cyberslav
Космическая музыка
День добрый, комрады!
Хотелось бы поделиться небольшой поделкой.
Я подумал и накидал небольшую программу, которая переводит данные о космических лучах в музыку:
Вкусняшка (для меня) в том, что это видео создано (сгенерировано) на графической карте, описывается парой шейдеров и это действительно можно назвать процедурной генерацией музыки :)
Правда, довольно простого уровня пока что.
Описание, как я это делал (для технарей): https://habr.com/ru/post/498218/
Ссылка на видос: https://www.youtube.com/watch?v=r-4RJfCpepE
Ссылка на аудио: https://soundcloud.com/arsenii-lisunov/cosmic-rays
**Описание для не-технарей есть на ЮТ и SC.
Но лучше всего это выглядит в шейдере: https://www.shadertoy.com/view/wsjyWK
Спасибо за внимание!
С радостью отвечу на вопросы или почитаю критику.