这是我制作的《Godot地形生成》系列视频,这里集合在一起供游戏爱好者学习和参考。
一:海陆图生成
二:生成河流
思路如下:
三:地图边缘下降
我们不想要处理玩家到达地图边缘的情况,因此最好的办法(我所可以想到的)就是让玩家到不了地图边缘。因此我们就需要使用地图边缘下降。
END:本文中的所有代码:
extends TileMap var noise = OpenSimplexNoise.new() enum {deep_ocean,ocean,grassland,desert,temperate_forest,tropical_forest,snow} var size = 512 func heat(pos): return abs(pos.y/(0.5 * size)) func falloff_value(pos): var value = max(abs(pos.x)/(0.5 * size),abs(pos.y)/(0.5 * size)) value = evalueate(value) return value func evalueate(x): var a = 3 var b = 2.2 var value = pow(x,a)/(pow(x,a) + pow(b - b * x,a)) return value func generate_land(size): print("[Generator]:Start generating lands") var x var y var i = 0 for x in range(-0.5 * size,0.5 * size): for y in range(-0.5 * size,0.5 * size): var pos = Vector2() pos.x = x pos.y = y var height = get_heightv(pos) var heat = heat(pos) if height >= -0.25 and height <= 0.4: if (height + 0.3) * heat < 0.05: set_cellv(pos,desert) else: set_cellv(pos,grassland) if height >= -0.5 and height <= -0.25: set_cellv(pos,ocean) if height <= -0.5: set_cellv(pos,deep_ocean) if height >= 0.4: set_cellv(pos,snow) i = i + 1 if i % 8192 == 0: print("[Generator]:",i/pow(size,2)) func generate(size): generate_land(size) # 生成海陆图 for i in range(randi() % 20): # 随机取点作为河流的水源 var x = randi() % size - 0.5 * size # -0.5 * size < x < 0.5 * size var y = randi() % size - 0.5 * size # the same as x if get_cell(x,y) == deep_ocean or get_cell(x,y) == ocean: continue generate_river(x,y) func get_heightv(pos): var value = noise.get_noise_2dv(pos) - falloff_value(pos) return value func get_closest_cell(cellP): var direction = Vector2(0,0) direction = Vector2(-1,0) var noise_value_min = 0 noise_value_min = get_heightv(cellP + direction) if get_heightv(cellP + Vector2(0,-1)) < noise_value_min: direction = Vector2(0,-1) noise_value_min = get_heightv(cellP + Vector2(0,-1)) if get_heightv(cellP + Vector2(1,0)) < noise_value_min: direction = Vector2(1,0) noise_value_min = get_heightv(cellP + Vector2(1,0)) if get_heightv(cellP + Vector2(0,1)) < noise_value_min: direction = Vector2(0,1) noise_value_min = get_heightv(cellP + Vector2(0,1)) return direction func create_pond(river): for i in range(river.size()): var r = pow(i/32,2) # r随距离变化的关系式 for x in range(river[i].x - 0.5 * r,river[i].x + 0.5 * r): for y in range(river[i].y - 0.5 * r,river[i].y + 0.5 * r): set_cell(x,y,1) func generate_river(x,y): var river = [] # 存储河流的路径 var cellP = Vector2() # 用作后来的遍历 cellP.x = x # 使起点为指定位置 cellP.y = y print("[Generator]:The position of the river is x:",x,"y:",y) while get_cellv(cellP + get_closest_cell(cellP)) != 1: # cellP + get_closest_cell(...)是为了 #后续添加功能是检测到自己所添加的河流cell var direction = get_closest_cell(cellP) cellP = cellP + direction # 对位置进行移动 river.append(cellP) # 在数组末尾加上当前cell set_cellv(cellP,1) create_pond(river) #使河流半径随与源头的距离变化 print("[Generator]:The length of the river is ",river.size()) func _ready(): print("[Generator]:The terrian generator begins") generate(size)
文中提到的网站:
函数图像在线绘制:https://www.desmos.com
Godot官方文档:https://docs.godotengine.org/zh_CN/latest/
暂无关于此日志的评论。