您好我创建程序用于生成程序图(大陆,岛屿,湖泊......)
有柏林噪音 我的程序生成2个映射,第一个映射0到512 x abs,第二个映像512到1024 x abs
带有柏林噪音,我会产生带有海滩,森林,山脉和湖泊的岛屿
现在我想添加道路和河流,但我不知道如何用perlin做到这一点,这可能吗?
我的代码:
import random
import noise
import numpy as np
from scipy.misc import toimage
import math
class Color:
# 0 -> 255
r = 0.0
g = 0.0
b = 0.0
a = 1.0
def __init__(self, r=0.0, g=0.0, b=0.0):
self.r = r
self.g = g
self.b = b
self.a = 1
def GetTuple(self):
return int(self.r), int(self.g), int(self.b)
def SetColor(self, r, g, b):
self.r = r
self.g = g
self.b = b
def Copy(self, color):
self.r = color.r
self.g = color.g
self.b = color.b
def SetWhite(self):
self.SetColor(1, 1, 1)
def SetBlack(self):
self.SetColor(0, 0, 0)
def SetColorFromGrayscale(self, f=0.0):
self.SetColor(f, f, f)
class GenerateMap:
def __init__(self, size=(50, 50), color_range=10, color_perlin_scale=0.025, scale=350, octaves=6, persistance=0.6,
lacunarity=2.0, x_starting_pos=0, y_starting_pos=0):
self.scale = scale
self.octaves = octaves
self.persistance = persistance
self.lacunarity = lacunarity
self.x_starting_pos=x_starting_pos
self.y_starting_pos=y_starting_pos
self.mapSize = size # size in pixels
self.mapCenter = (self.mapSize[0] / 2, self.mapSize[1] / 2)
self.heightMap = np.zeros(self.mapSize)
# self.colorMap = [[Color() for j in range(self.mapSize)] for i in range(self.mapSize)]
self.randomColorRange = color_range
self.colorPerlinScale = color_perlin_scale
self.lightblue = [0, 191, 255]
self.blue = [65, 105, 225]
self.darkblue = [0, 0, 139]
self.green = [34, 139, 34]
self.darkgreen = [0, 100, 0]
self.sandy = [210, 180, 140]
self.beach = [238, 214, 175]
self.snow = [255, 250, 250]
self.mountain = [139, 137, 137]
self.threshold = -0.01
def return_initial_blank_map(self):
return self.heightMap
def get_map_corners(self):
nw = self.heightMap[0][0]
ne = self.heightMap[0][len(self.heightMap[0])-1]
sw = self.heightMap[len(self.heightMap)-1][0]
se = self.heightMap[len(self.heightMap)-1][len(self.heightMap[0])-1]
return nw, ne, sw, se
def get_map_start_position(self, start_position):
pass
def generate_map(self, map_type=""):
random_nr = random.randint(0, self.mapSize[0])
random_nr = 3
for i in range(self.mapSize[0]):
for j in range(self.mapSize[1]):
new_i=i+self.y_starting_pos
new_j=j+self.x_starting_pos
self.heightMap[i][j] = noise.pnoise3(new_i / self.scale, new_j / self.scale, random_nr, octaves=self.octaves,
persistence=self.persistance, lacunarity=self.lacunarity,
repeatx=10000000, repeaty=10000000, base=0)
print("monochrome map created")
if map_type is "island":
gradient = self.create_circular_gradient(self.heightMap)
color_map = self.add_color(gradient)
else:
color_map = self.add_color(self.heightMap)
return color_map
def add_color(self, world):
color_world = np.zeros(world.shape + (3,))
# print(color_world)
for i in range(self.mapSize[0]):
for j in range(self.mapSize[1]):
if world[i][j] < self.threshold + 0.02:
color_world[i][j] = self.darkblue
elif world[i][j] < self.threshold + 0.03:
color_world[i][j] = self.blue
elif world[i][j] < self.threshold + 0.058:
color_world[i][j] = self.sandy
elif world[i][j] < self.threshold + 0.1:
color_world[i][j] = self.beach
elif world[i][j] < self.threshold + 0.25:
color_world[i][j] = self.green
elif world[i][j] < self.threshold + 0.6:
color_world[i][j] = self.darkgreen
elif world[i][j] < self.threshold + 0.7:
color_world[i][j] = self.mountain
elif world[i][j] < self.threshold + 1.0:
color_world[i][j] = self.snow
print("color map created")
return color_world
def create_circular_gradient(self, world):
center_x, center_y = self.mapSize[1] // 2, self.mapSize[0] // 2
circle_grad = np.zeros_like(world)
for y in range(world.shape[0]):
for x in range(world.shape[1]):
distx = abs(x - center_x)
disty = abs(y - center_y)
dist = math.sqrt(distx * distx + disty * disty)
circle_grad[y][x] = dist
# get it between -1 and 1
max_grad = np.max(circle_grad)
circle_grad = circle_grad / max_grad
circle_grad -= 0.5
circle_grad *= 2.0
circle_grad = -circle_grad
# shrink gradient
for y in range(world.shape[0]):
for x in range(world.shape[1]):
if circle_grad[y][x] > 0:
circle_grad[y][x] *= 20
# get it between 0 and 1
max_grad = np.max(circle_grad)
circle_grad = circle_grad / max_grad
grad_world = self.apply_gradient_noise(world, circle_grad)
return grad_world
def apply_gradient_noise(self, world, c_grad):
world_noise = np.zeros_like(world)
for i in range(self.mapSize[0]):
for j in range(self.mapSize[1]):
world_noise[i][j] = (world[i][j] * c_grad[i][j])
if world_noise[i][j] > 0:
world_noise[i][j] *= 20
# get it between 0 and 1
max_grad = np.max(world_noise)
world_noise = world_noise / max_grad
return world_noise
paperColor = Color(212, 161, 104)
waterColor = Color(0, 20, 28)
map_data = GenerateMap((512, 512), x_starting_pos=0, y_starting_pos=0)
print("Generator initiallized")
mono_map = map_data.generate_map("island")
print("map generated")
toimage(mono_map).show()
print("map displayed")
map_data = GenerateMap((512, 512), x_starting_pos=512, y_starting_pos=0)
print("Generator initiallized")
mono_map = map_data.generate_map("island")
print("map generated")
toimage(mono_map).show()
print("map displayed")
答案 0 :(得分:0)
这似乎表明,道路生成大部分是使用groth算法完成的。为此,您不需要Perlin噪声,只需一个可以生成随机片段的随机发生器即可。然后,您可以添加自己喜欢的约束(使用实际道路限制角度,检查您是否不在水上建筑,等等)。
https://martindevans.me/game-development/2015/12/11/Procedural-Generation-For-Dummies-Roads/
如果要使用Perlin噪声,可以尝试计算与噪声值关联的高度图的水平集。但是结果可能看起来不太好,我也不会推荐这种方法。