Итак, сегодня мы поговорим о генерации пещер и карт высот с помощью шума. Это будет Гауссовский шум, его легче всего сделать в Python Pillow.
Первые можно использовать для генерации карт высот или текстур, а вторую для генерации пещер.
Для начала расскажу, как работает алгоритм для генерации карт высот. Мы просто берем обычный пиксельный шум, а потом размываем его функией из модуля Pillow:
im1 = im1.filter(ImageFilter.GaussianBlur(radius = 3)) #im1 - картинка с пиксельным шуом
Приступим к коду.
Сначала импортируем все библиотеки и загрузим картинки.
from PIL import Image, ImageDraw, ImageFilter #Выгружаем все из модуля Pillow.
from random import * #Импортируем библиотеку random, для генерация псевдослучайных чисел)))
im1 = Image.open("back.png") #Загружаем фон, над которым будем генерировать шум. это просто черная картинка 160 на 160 пикселей.
draw = ImageDraw.Draw(im1) #Создаем холст для нашего фона.
width = im1.size[0]
height = im1.size[1] #Получаем размер фона.
pix = im1.load() #Получаем все пиксели из фона.
Теперь давайте генерировать шум!
for x in range(width):
for y in range(height):
sr = randint(0, 255) #Берем случайное число.
draw.point((x,y), (sr,sr,sr)) #И рисуем его на холсте.
#По сути, ничего с фоном мы не делаем, нам просто нужен ImageDraw.Draw
#Который мы будем заполнять случайными пикселями.
теперь выведем это на экран функцией im1.show()
Теперь надо размыть его.
im1 = im1.filter(ImageFilter.GaussianBlur(radius = 3))
im1.show()
У нас теперь есть шум, который мы можем использовать))) Но еще можно доработать это, чтобы получать карты подземелий.
Для начала, мы используем для работы с изображениями RGB-представление, и 8-битную запись, а значит каждый пиксель у нас записан в виде кортежа:
(r, g, b) #Значение каждого элемента - от 0 до 255.
Чтобы сгенерировать такие пещеры, мы будем округлять значение яркости каждого пикселя. Если оно больше половины максимальной яркости - а это в 8-битной записи 255, то мы заменяем яркость у пикселя на 255. Если нет, то заменяем яркость пикселя на 0.
draw = ImageDraw.Draw(im1)
pix = im1.load() #Тут загружаем данные об размытом изображении.
for x in range(width):
for y in range(height):
r = pix[x, y][0] #
g = pix[x, y][1] #Тут как когда мы генерировали пиксельный шум, поэтому
b = pix[x, y][2] #не буду обьяснять.
if r > 127:
r = 255 #
g = 255 #Проверяем, больше ли r 127 (это 255 / 2). Проверяем именно r
b = 255 #Потому-что предполагается, что g и b будут ему равны, т. к. шум монохромный
else:
r = 0
g = 0
b = 0
draw.point((x, y), (r,g,b)) #Рисуем точку на холсте.
По сути все.
Еще можно в конце написать im1.save('res.png') чтобы сохранить сгенерированную карту.
Комментарии (10)
berez
21.01.2022 15:18+2Так это… Ну ладно карта высот — будут кочки, это красиво. Но карта пещер должна ведь каким-то требованиям по связности отвечать? А то получится гора, вся дырявая внутри, но при этом не имеющая ни единого прохода в глубину.
Myxach
21.01.2022 16:12+1Можно брать результат за основу, а потом уже на этой основе генерировать новую карту. Допустим связать закрытые участки(игрок в них попасть никак не может) с открытыми (в которые он может попасть)
pehat
21.01.2022 17:27+1С каких это пор заблюренный белый шум является градиентным?
VadimCoder Автор
22.01.2022 17:36Я ошибся, думал градиентный шум это просто шум с плавными перепадами. Уберу упоминание.
DistortNeo
Не нужно изобретать велосипеды.
https://habr.com/ru/post/430384/
https://habr.com/ru/post/342906/
VadimCoder Автор
Первая статья - про шум Перлина.
Вторая - про шум Перлина.
Как это связано с моей статьей?)
А по итогу полный велосипед, да.
DistortNeo
Так я специально искал статьи по запросу "шум перлина", потому что он активно используется для процедурной генерации всего, чего только можно.
VadimCoder Автор
Но у меня в статье не шум Перлина, а шум Гаусса. Это вроде как не одно и то же)
DistortNeo
Ваша статья начинается со слов:
Обычно для этой цели используется шум Перлина.
Если же вы используете для этой задач другой шум (шум Гаусса), стоит обосновать, чем же он лучше. Ну либо просто признаться, что вы не изучали матчасть и придумали велосипед.
VadimCoder Автор
Признаюсь, матчасть совсем не изучал. Но других статей на эту тему (шум Гаусса для проц. генерации) не видел.