Всем привет.
Начну с небольшого вступления. Я уже давно занимаюсь созданием игр, начинал с флешовых игр в вк, потом пытался там же сделать игру про Бровастика, но не очень удачно. После фейла с Бровастиком ушел работать в небольшую компанию над мобильной игрой. Большой геймдев это весело, но душа у меня лежит всё же к чему-то своему. Поэтому решил снова попробовать в инди-геймдев. На этот раз начал лепить игру уже на Unity.
Я фанат процедурной генерации, ибо вся жизнь это одна сплошная процедурная генерация, поэтому выбор пал на рогалик. А и ещё, потому что в теории надо делать меньше контента. А это важно для инди-разработчика.
У игры уже есть концепт, сеттинг и прочий "сырой контент". Но показывать их я вам не буду.
А лучше расскажу о фундаментальных штуках!
Итак, что представляет из себя игра? Это длинное (около 1 км в игровых условностях) поле с видом сбоку, по которому перемещается персонаж и "не только лишь персонаж". По бокам переходы на левую и правую локацию, а в центре можно найти тропинки на верхнюю и нижнюю локацию.
Таким образом, мы можем соединить вместе большое количество локаций и получить глобальную карту, которая будет выглядеть как-то так (по цветам очевидно, где поля, леса, реки, горы и т.д.):
Выше представлен один из сгенерированных вариантов глобальной карты. Генерация происходит достаточно простым способом:
1) Первичное засеивание. Основные типы локаций, такие как леса, сначала добавляются в случайных местах по некой карте весов (например, для леса эта карта сосредоточена в центре, чтобы не пугать игрока страшными лесами в начале игры), после чего происходит случайное расширение лесного биома по фронту, то есть расширяется по сторонам.
2) Генерация рек. Реализована достаточно костыльным способом: есть стартовая точка и вектор направления реки, по которому река пытается пройти. Если ей это не удается (например, врезалась в скалу), то она "умирает".
Генерация мостов у рек происходит также топорно: на каждых пять рек должен быть один мост в случайно-подходящем месте. Такая генерация мостов не годится, так как вероятно появление изолированных участков суши. Чтобы это исправить, надо дополнительно проходиться волновым алгоритмом по каждому проходимому участку суши и если обнаружится его изолированность, то добавлять как минимум несколько мостов через реки для него. Но мне хочется сделать все по скорее, так что пока что и так сойдет :)
3) Генерация структур. К ним пока что относятся только городские локации. Основная идея этого алгоритма в том, что все локации добавленные до этого имеют свой эффект усиления/ослабления на карте весов. Если по-простому, то возле рек городская локация появится с большей вероятностью, а возле болот с меньшей вероятностью.
4) Генерация дорог/мелких рек. До этого этапа пока что не дошел, но позже обязательно вернусь к нему. Основная идея в том, чтобы соединять городские локации между собой дорогой. Для этого надо будет обратиться снова к волновому алгоритму + щепотка случайности.
Итак, с глобальной картой мы разобрались, а чего на самих локациях то будет твориться? А твориться там будет полный холмодром! За основу взята идея поверхности из gravity defied:
Только без мотоциклов. У нас игрок будет перемещаться на своих двоих. Вот собственно ранний результат сгенерированной поверхности:
Выглядит пока что не очень, но является достаточно фундаментальным. По сути основной упор генерации будет на создании двухмерного массива точек поверхности. А уже потом оно будет раздуваться до полноценного меша поверхности и процедурно текстурироваться. А там и остальные вещи, такие как деревья, можно будет расставлять по поверхности.
Если говорить, про генерацию двухмерной карты, то тут также всё просто:
1) Генерация структур. В зависимости от типа локации получаем случайную выборку структур. Например, для города это будут разные постройки, дороги. А для леса водоемы и лесные массивы (плотные скопления деревьев).
2) Генерация кривой. Теперь на основе структур мы знаем, где нам надо иметь ровную поверхность (под зданиями, например), а где допустимо делать холмистую. Какие-то структуры будут создавать специфичные кривые (например у рек будет чашеобразное дно). Также здесь появятся ещё две условности: во-первых, это высота локации. Зная высоты соседних локаций, мы сможем более гибко манипулировать генерацией. Вот пример:
Помимо высоты, так же добавляется фактор "шероховатости" локации. Чем выше, тем более холмистой локация будет, и наоборот.
Теперь у нас есть все необходимое для создания кривой. Просто кодим и получаем это:
На этом первая часть закончилась. Вторая часть если и будет, то не скоро, так как я работаю один и медленно.