
Разработка игры -> Restoration of Teim
7 постов
7 постов
9 постов
5 постов
6 постов
5 постов
В продолжение к посту: Процедурный мир из огромных гексов (ч.1)
И так, продолжаю улучшать и дорабатывать генерацию своего гексо-мира. Первое чем хотелось бы похвастаться, отныне мир в лучших традициях господина Терри Пратчетта имеет форму диска!
А теперь к важным доработкам. В прошлой части я остановился на том что сделал генерацию самих гексов, с группами высот и их перепадами. И на этом моменте возник вопрос
А как по этому перемещаться?
Проблема в том что игроку нужно же как-то бегать по миру, а так как мир большой, и акцент в игре планируется на исследовании, бегать надо будет много. И как бегать по миру состоящему из групп склонов с углом в 90 градусов на разных высотах в диапазоне от 10 до 50? Никак, удаляй
У меня было несколько идей:
1 - Винтовые лестницы на гексах. Её я отбросил сразу из-за неудобства (Вы представляете сколько игроку надо будет по ним "кружить"? И технически реализовать сложновато немножко)
2 - Лестницы / Лианы (Одним словом Вертикальный лаз) - Я этот способ даже сделал, пускай и без графики, кинул с гексов с большим перепадом высот вниз условную лестницу.
Но попробовал так перемещаться по миру, я задушился об это говно решение. Игрок минут за 10 может перебежать через десятки гексагонов и групп высот, и унылое лазанье отобъет всё желание в эксплоринге мира.
Ну и пришел к идее "Склонов", градусов под 40-45. Не без подсказок от читателей:
В общем идея проста, если между гексами в двух разных группах высот, перепад не выше 20, то у некоторых случайных гексов группы создаём склон, тайлим его, навешиваем коллайдер, и вуаля. Звучит конечно проще чем реализуется... Повозится пришлось знатно, но результат оправдал своих заморочек:
Ну и само видео. На нём можно заметить что ёлочки генерируются прям в склоне, но это я поправлю чуть позже.
Теперь мы можем с комфортом перемещаться по миру, не прерываясь на бесконечное скалолазанье и винтовые лестницы. Как по мне отличное решение!
Так же в мире появилась заготовка под море и водичку. Пока страшненькая но есть (Раньше воды вообще не было, а кроме суши была "пустота"):
Ну и наконец я начал работать над механизмом генерации структур, замки, руины, деревни, вот это всё. Вот например один сегмент Замка игрока (их всего 3), сгенерировавшийся в мире:
Но о генерации структур я подробно опишу когда её доделаю, в следующем посте. Спасибо всем за внимание!
Это будет странный пост, на странную тему, кому-то кстати очевидную, кому-то нет) Но почему бы не написать?
Играя в видеоигры, особенно во всякие приключения в открытом мире и RPG, в процессе приключений вы встретите разрушаемые бочки, ящики, горшки, в подземелье вас будут караулить гоблины и тролли, а в соседней деревне старейшина будет ждать вас с заданием, ну и торговец готовый скупить все барахло что вы выбьете из горшков и гоблинов.
Так вот о чем я, забавно что всё описанное выше, это разности одной сущности, причём буквально "Сущности", оно же Entity
То есть условный горшок который вы разбили и из которого выпали монетки это сущность, и гоблин которого игрок зарубил, да даже сам игрок, это тоже сущность, только "высшего поколения". Это стандартизация и наследование
Надо это зарисовать:
Криво-косо но зарисовал)
Это эдакое "развитие" сущностей при разработке игр, вариаций может быть много, но это один из
Базово, разработчик закладывает "Сущность", сущность нематериальна и не годится для наполнения мира, у неё нет визуализации. Сущность это холст с базовыми параметрами общими для всех последующих вариаций.
Ну например здоровье, у всех последующих поколений будет здоровье, даже у игрока, или сопротивляемость
Так же помимо параметров в сущность закладываются алгоритмы применимые ко всем последующим. Ну например получение урона. Каждая сущность может получить пиздов урон. Этого достаточно для базовой сущности, остальные параметры и функционал будут накидываться уже на следующих поколениях
А зачем? Почему бы не сделать одно, универсальное поколение сущности применимое ко всем?
Ответ довольно прост: Избыточность и разное назначение
Но сначала в двух словах о самом понятии "Поколение", это наследование классов в программировании. Класс-наследник хранит в себе все заданные параметры и функции предка (Публичные)
И так, про "Избыточность":
Не всем сущностям нужны все параметры. Ну например зачем условной бочке, базовые характеристики силы, выносливости, и значения урона как у существа?
Смысл существования бочки, стоять и ждать пока игрок её разобьёт, и при разбитии выдать 3-6 монеток.
Или например зачем сущности игрока встроенная система ориентации на местности от Моба? Игрок отлично определить куда идти сам, и подвинет себя с помощью WASD
Ну я думаю вы поняли
А зачем вообще эти наследования и поколения? Почему бы под все нужды не создать индивидуальный класс? Ну для монстров Monster для бочек Prop?
Для систематизации и удобства.
Самое очевидное - не нужно заново указывать одно и тоже, ты один раз задал сущности здоровье, существу параметры и характеристики, типа выносливости, силы, урона и.т.д.
Ты один раз написал мобу алгоритм поиска пути, и все его наследники, НПС, монстры, торговцы, боссы и.т.д уже будут знать как двигаться в пространстве.
Ну и менее очевидное - Условия и проверки.
Вот например меч игрока проходит сквозь объект. В мече прописано что при столкновении с чем-то надо проверить что это и нанести урон.
И вы представляете какая чехарда и полотно из кода будет, если все классы существ были бы не родственными? У каждого индивидуальные параметры здоровья, и нужно или каждому прописывать обработку получения урона, или делать глобальную. К тому же нужно будет задать перечень классов которым вообще можно наносить урон.
В общем много возни
А так все просто, меч просто проверит: Это сущность? (Поколение не важно, ведь здоровье и алгоритм нанесения урона существует в самом базовом поколении 0) Если да, то наношу урон. И всё
Так что в следующий раз когда будете бить гоблинов в подземелье, задумайтесь, ведь ваш игрок и они, возможно, функциональные родственники, хоть и очень далекие)
Всем спасибо за внимание! Рад если кому-то это полотнище текста и кривой паинт покажеться интересным!
Как я создаю себе несложный процедурный мир не привлекая внимания санитаров
Захотел сделать небольшую игру чтоб вот тебя закидывало в случайный фентези мир, а ты там "приключался", боссов бил, королевство свое строил. Что-то похожее на Terraria.
Но что делать если ты рукожоп не хочешь особо заморачиваться с качественной процедуркой игрового мира?
Сделать мир из огромных гексагонов? Звучит как хуета отличная идея! 💡
1. Генерируем двумерную карту
Перед тем как создавать гексагоны надо сначала создать/сгенерировать сам ландшафт в виде двумерной матрицы, где будет вообще ландшафт, перепады высот, какие будут в каком биоме и.т.д.
Предварительно я разделил для себя мир на несколько "слоёв":
1. Карта поверхности, на ней будет определена структура мира, в каких ячейках гексы вообще будут существовать собственно. База одним словом
2. Карта высот. На этой карте будут заданы группы высот для гексов, чтоб мир был не "плоский"
3. Карта биомов. На этой карте мы сформируем будущие группы биомов.
4. Карта рек и озер. Несмотря на "крупногексагональный" форм-фактор будущего мира, я хочу чтоб по нему текли реки и были озера. Эта карта пометит условный гекс (или же ячейку массива) как имеющую реку, а там разберёмся
Вот они, слева направо, их боялся весь проект
"Чё ты там нахуевертил" - Скажите вы щурясь как азиат из мема
Я художник! Я так вижу! На самом деле это техническая визуализация уже сформированного мира в 2D матрице, мне же надо было как-то смотреть на то что там выходит вообще.
"И шо ты, пёс, даже не расскажешь как ты это генерировал?" - спросит моя воображаемая аудитория.
А я вам отвечу! Нет. Сейчас все обьясню! И так, А-а-а-а-втомобиль лгоритм в студию!
Смотрите, существуют адекватные разработчики, которые, когда речь заходит за процедурную генерацию, в первую очередь думают в сторону шумов, тот же Шум перлина (Perlin Noise) это идеальный способ выстроить и попиксельную 2д карту ландшафта, с перепадами высот (чем темнее пиксель тем выше). Выглядит он вот так:
Но причём тут адекватные разработчики, и я)
Я сделал это по принципу который придумал себе ещё на первом курсе, саморастущие ядра (шо?)
Если вкратце, в двумерном массиве ограниченном размере мира (например сетка 64×64 ячейки) в случайных местах создается расчетное количество "ядер" генерации, каждое ядро помечает свой адрес как будущую поверхность сразу, и помимо этого несёт в себе случайное количество "зарядов".
Каждую итерацию ядро тратит на то, чтобы "расширится" в случайное направление сетки, захватив, и пометив как будущую поверхность и захваченную ячейку, и так пока у всех ядер не закончатся заряды.
Выглядит это вот так, и в принципе формируется нормальный +- ландшафт:
Жёлтые - ядро
Синие - захваченные ядром ячейки
Точно такой же принцип используется и для карты высот и карты биомов, только теперь ядра формируется в ячейках адреса которых уже являются "поверхностью".
Создаются группы высот которым назначаются высоты, которые при генерации самих гексов собсна говоря и передадутся.
В этот раз ядра, это ромбики, а разным цветом обозначеныгруппы высот:
Ну и абсолютно тот же принцип с биомами, только в ячейках групп биомов хранится ссылка на соответствующий экземпляр класса Biome
Круто! Теперь у нас есть карты двумерных массивов содержащие все необходимые данные для генерации крупногексагонального мира
Используя гайды из Habr свои навыки и умения, я написал скрипт в котором циклом производится проходка по, сохраненным ранее в двумерные массивы, картам данных, и на основе этих данных формируется... Пока только гексагональная 3д структура с разными высотами:
Красиво, но пусто, а давайте запустим туда нашего персонажика которого я создал "за кадром"
Теперь вообще и пусто и некрасиво... Миша все хуня давай по новой! Тебе так никто денег не даст!
Добавим генерацию биомов, чтобы гексам относительно их адреса в карте биомов присваивался соответствующий биом:
Во, уже лучше! Это правда "биомы" пока условные, просто гексы те же, с разными структурками, на итоговый вид это особо не повлияет. Так что нужно на гекс навесить деталей. Tiling time!
Во, так лучше, только надо вот эти стыки на ровной поверхности убрать.
А ещё добавлю "детали" какие нибудь, пусть будут ёлочки в биоме "лес", пока с временной графикой, пара текстурок.
Сделаю банальной "россыпью" этих елочек на каждый гекс
Уже что-то похожее на мир! На этом пока все, впереди ещё туева хуча работы, оптимизация отрисовки деталей (LOD), механизм генерации структур в мире (всякие замки, руины, домики набигающие) и.т.д
+ Мне ещё предстоит решить проблему как игроку перемещаться между гексами с сильными перепадами высот... Лестницы? Винтовые пещеры? Прыгучие платформы? Лианы? Надо думать...
p.s. У самих гексов реализован LOD, и их детализация уменьшается на отдаленном расстоянии от игрока, а дальше и вовсе отключается. Так же я сделаю с деталями на гексах я думаю.
Спасибо всем тем двум людям которые дочитают эту тягомотину до конца!
Несколько дней потратил на этот ролик, местами есть косяки и странные кадры, но в целом как по мне вышло довольно неплохо
Музыка (Оригинал) - Наутилус Помпилиус "Скованные одной цепью"
AI Cover - https://suno.com/song/bceb7d2e-c1a7-4ca4-995b-4129d537f7f2
Арты сгенерированны с помощью нейросети "Шедеврум"
Анимация артов сделана с помощью нейросети "Luma AI"
Моя делать игра без бюджета, и поэтому решил сделать музыку для своей адвенчуры с использованием нейросети Suno AI, и результат довольно приятный)
Так же хочу обратить внимание что здесь вообще всё сделано нейросетями:
Арт - Шедеврум от Яндекса
Музыка - Suno AI
Анимация арта - Luma AI
Нейросети конечно и впечатляют, и пугают одновременно, еще пару-тройку лет назад они могли рисовать невнятные каракули, а за видео и музыку и речи особо не шло, а теперь вот, они ж ещё и код пишут...
Баловался с нейросетью Suno AI, и уж больно мне зашло как это звучит, решил поделиться)
Арт сгенерировал в другой нейронке "Шедеврум"