這是我幾年前寫的一堂課,爲我的roguelike原型創建了一張世界地圖DomeriaRL。相關部分在__generate
method。
它將噪聲應用於高度貼圖,對其進行標準化並基於高度貼圖的值創建貼圖。
我使用顏色貼圖來創建從一種瓷磚到另一種瓷磚的平滑過渡。
from constants.constant import *
from world import World
from worldtile import WorldTile
class WorldGenerator(object):
"""Randomly generates a new world with terrain and objects"""
def regular(self):
"""Randomly generate a new world with some water, swamps, hills, some objects etc"""
idx = [ 0 , 15, 75, 90, 101 ] # indexes of the keys
col = [ T.Color(0,100,100),
T.Color(0,75,0),
T.Color(50,150,0),
T.Color(150,120,80),
T.Color(180,180,180)]
map=T.color_gen_map(col,idx)
tiles = zip(idx, [[SWAMP, PLAINS],
[PLAINS, FOREST],
[HILLS, FOREST],
[HILLS, HILLS, MOUNTAINS],
[HILLS, MOUNTAINS,MOUNTAINS]])
world = self.__generate(map, tiles)
return world
def __generate(self, colormap, mtiles, noise_zoom=1, noise_octaves=10):
hm = T.heightmap_new(WORLD_WIDTH, WORLD_HEIGHT)
hm1 = T.heightmap_new(WORLD_WIDTH, WORLD_HEIGHT)
hm2 = T.heightmap_new(WORLD_WIDTH, WORLD_HEIGHT)
noise = T.noise_new(2)
T.heightmap_add_fbm(hm1, noise, noise_zoom, noise_zoom, 0.0, 0.0, noise_octaves, 0.0, 1.0)
T.heightmap_add_fbm(hm2, noise, noise_zoom*2, noise_zoom*2, 0.0, 0.0, noise_octaves/2, 0.0, 1.0)
T.heightmap_multiply_hm(hm1, hm2, hm)
T.heightmap_normalize(hm, mi=0.0, ma=1)
tiles = {}
# 0...100 -> value from noised heightmap
for x in xrange(0, 101):
lower = [c for c in mtiles if c[0] <= x][-1] # tile is between lower and upper color
upper = [c for c in mtiles if c[0] > x][0]
# calculating percentage
lower_c = x - lower[0]
upper_c = upper[0] - x
count = lower_c + upper_c
tiles[x] = colormap[x], lower[1], int(upper_c * 1.0/count * 100), upper[1]
# generate world grid
grid = []
for x in xrange(WORLD_WIDTH):
grid.append([])
for y in xrange(WORLD_HEIGHT):
hm_v = T.heightmap_get_value(hm, x, y)
grid[x].append(WorldTile(*tiles[int(hm_v * 100)]))
T.heightmap_delete(hm)
T.heightmap_delete(hm1)
T.heightmap_delete(hm2)
objects = []
while len(objects) < 5:
for x in xrange(WORLD_WIDTH):
for y in xrange(WORLD_HEIGHT):
r = random.randrange(0, 10000)
pos = [wo for wo in WORLDOBJECTS if wo.chance >= r and grid[x][y].tile in wo.tiles]
if pos:
o = random.choice(pos).create(x, y)
objects.append(o)
return World(grid, objects)
一個例子世界地圖看起來是這樣的:
注意,這個遊戲使用libtcod 1.5.1b1,有的函數名在新版本改變。
幾年前,他用不同的地下城/世界發電機寫了一個rogulike原型,使用litcod/noise。你可以在這裏找到它(https://bitbucket.org/BigYellowCactus/domeriarl)(注意它使用的是舊版本的litcod版本),尤其是['worldgenerator.py'](https://bitbucket.org/BigYellowCactus/ domeriarl/src目錄/ d9a99e7ca119d12d4251b4741034e631c23d991f/src目錄/世界/ worldgenerator.py?在=默認值)。 – sloth 2013-05-07 10:17:08
感謝Dominic,這真的太棒了!告訴我,如果我得到這個權利:你創建一個高度圖,添加噪音,然後根據每個位置的高度分配瓷磚? – 2013-05-07 19:44:38