python

Генерация подземелий на Python с изпользованием Pillow

  • суббота, 22 января 2022 г. в 00:42:08
https://habr.com/ru/post/647023/
  • Python


Итак, сегодня мы поговорим о генерации пещер и карт высот с помощью шума. Это будет Гауссовский шум, его легче всего сделать в 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') чтобы сохранить сгенерированную карту.