marshroom/dungeon-plot/dungeon.py

103 lines
2.8 KiB
Python

import matplotlib.pyplot as plt
from matplotlib import colors
import numpy as np
from perlin_noise import PerlinNoise
import cv2 as cv
import os
from PIL import Image
import sys
data = np.random.rand(16, 16)
def generate_base_map(filename):
print("generating base map...")
cmap = colors.ListedColormap(['white', 'black'])
bounds = [0, .5, 1]
norm = colors.BoundaryNorm(bounds, cmap.N)
#dpi=96
#size=512
#fig, ax = plt.subplots(1, 1, figsize=(size/dpi, size/dpi))
fig, ax = plt.subplots()
ax.imshow(data, cmap=cmap, norm=norm)
plt.axis('off')
plt.savefig(filename, bbox_inches='tight', pad_inches=0)
im = Image.open(filename)
out = im.resize((512,512))
out.save(filename)
#plt.savefig('../marshroom/dungeon/dungeon.png', bbox_inches='tight', pad_inches=0, dpi=dpi)
def generate_perlin(filename):
print("generating perlin noise...")
noise = PerlinNoise(octaves=10, seed=1)
xpix, ypix = 512, 512
pic = [[noise([i/xpix, j/ypix]) for j in range(xpix)] for i in range(ypix)]
plt.imshow(pic, cmap='gray')
plt.savefig(filename, bbox_inches='tight', pad_inches=0)
im = Image.open(filename)
out = im.resize((512,512))
out.save(filename)
def generate_loot_probability_map(filename, noise_filename, mask_filename):
print("generating loot probabilities...")
#noise = cv.imread(noise_filename)
mask = cv.imread(mask_filename, 0)
mask = cv.bitwise_not(mask)
kernel_size = 32
kernel = np.ones((kernel_size, kernel_size), np.uint8)
eroded = cv.erode(mask, kernel)
# use quarter-circle kernels to build up shadows in 90 degree corners
centres = [
(-1, -1),
(-1, kernel_size+1),
(kernel_size+1, -1),
(kernel_size+1, kernel_size+1)]
joined = mask.copy()
for centre in centres:
circle_kernel = np.zeros((kernel_size, kernel_size), np.uint8)
cv.circle(circle_kernel, centre, kernel_size, 255, -1)
dilated = cv.dilate(eroded, circle_kernel, iterations=1)
joined[dilated == 0] = 0
# we want white in the corners and black on floors and in wall so we need to invert the colours
inverted = cv.bitwise_not(joined)
# inverting it turns the shadows white, but now the inside of the walls are also white, where we want them to be black.
# in the base map the inside of walls is white.
# we therefore want to set pixels in the output to zero where the base map is white
invmask = cv.bitwise_not(mask)
inverted -= invmask
# we're left with some narrow artifacts which we can erode away
erodedinv = cv.erode(inverted, np.ones((3,3),np.uint8))
# modulate with noise?
cv.imwrite(filename, erodedinv)
noise = 'perlin.png'
map = 'map.png'
loot = 'loot.png'
#generate_perlin(noise)
#generate_base_map(map)
generate_loot_probability_map(loot, noise, map)