Pull to refresh

Генерация ландшафта как в MineCraft

Reading time2 min
Views34K
image

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

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

И так собственно о том, как я делал. Сначала я попробовал делать на основе шума Перлина (строил карту высот и по ней уже создавал 3д ландшафт), получилось достаточно интересно, но как видно не очень-то и похоже на Minecraft.

В 2д варианте это выглядело вот так.
Упрощенный пример кода для шума Кена Перлина.

for x:=-20 to 20 do
for y:=-20 to 20 do begin
n := x + y * 57;
n := (n shl 13) xor n;
ObjectCount:=ObjectCount+1;
Engine.AddProxy(PerlinCube,RootCube,'Cube'+IntToStr(ObjectCount),FileListBox1.FileName,x,2*(1 - ((n * (n * n * 15731 + 789221) + 1376312589) and $7fffffff) / 1073741824),y,0,1,0,1,1,1);
Map2[x,y]:='Cube'+IntToStr(ObjectCount);
end;




В 3д смотрится лучше, да и то из за добавленного уровня воды.


После прочтения статьи модифицировал, так как примерно было раньше в самой игре. Для каждого столба блоков высота равнялась (общ_высота + (шероховатость*детали))*64+64. От себя я добавил простое сглаживание. Получилось гораздо лучше.

Вот упрощенная часть кода для небольшого куска:

pod:=4;
nerov:=2;
melk:=1;

for x:=-20 to 20 do
for y:=-20 to 20 do begin
nerov:=Random(3);
melk:=Random(2);
Map1[x,y]:=((pod+(nerov+melk))*5+5)-25;
end;

Engine.AddUCube(RootCube,'PerlinCube',FileListBox1.FileName,x,(1 - ((n * (n * n * 15731 + 789221) + 1376312589) and $7fffffff) / 1073741824),y,0,1,0,1,1,1);

for x:=-20 to 20 do
for y:=-20 to 20 do begin
ObjectCount:=ObjectCount+1;
Engine.AddProxy(PerlinCube,RootCube,'Cube'+IntToStr(ObjectCount),FileListBox1.FileName,x,map1[x,y],y,0,1,0,1,1,1);
Map2[x,y]:='Cube'+IntToStr(ObjectCount);
end;



Я заснял поэтапно.

1. Построен кусочек карты.


2. Добавлен шум Перлина.


3. Первый цикл сглаживания.


4. Второй цикл сглаживания.


5. В конце немного деревьев что было не так уныло.


Результатом я доволен, правда для полноценной игры вроде Minecraft он не дотягивает, но для 2д аркады в самый раз. Именно туда я прикрутил генерацию разреза ландшафта и отбрасывал кубы которые выше или ниже границы что бы было более удобно с точки зрения геймплея аркады.


Ссылки.
Кому интересно вот ссылка на перевод статьи о ландшафте Minecarft.
Очень понравилась статья о шуме Перлина ссылка.
Так же напомнили про очень интересную статью по генерации ландшафтов ссылка.
Tags:
Hubs:
+21
Comments16

Articles