Генерация подземелий на Python с изпользованием Pillow
- суббота, 22 января 2022 г. в 00:42:08
Итак, сегодня мы поговорим о генерации пещер и карт высот с помощью шума. Это будет Гауссовский шум, его легче всего сделать в Python Pillow.
Первые можно использовать для генерации карт высот или текстур, а вторую для генерации пещер.
Для начала расскажу, как работает алгоритм для генерации карт высот. Мы просто берем обычный пиксельный шум, а потом размываем его функией из модуля Pillow:
im2 = 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()
У нас теперь есть градиентный шум, который мы можем использовать))) Но еще можно доработать это, чтобы получать карты подземелий.
Для начала, мы используем для работы с изображениями RGA-представление, и 8-битную запись, а значит каждый пиксель у нас записан в виде кортежа:
(r, g, b) #Значение каждого элемента - от 0 до 255.
Чтобы сгенерировать такие пещеры, мы будем округлять значение яркости каждого пикселя. Если оно больше половины максимальной яркости - а это в 8-битной записи 255, то мы заменяем яркость у пикселя на 255. Если нет, то заменяем яркость пикселя на 0.
draw = ImageDraw.Draw(im2)
pix = im2.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)) #Рисуем точку на холсте.
По сути все.
Еще можно в конце написать im2.save('res.png') чтобы сохранить сгенерированную карту.