这是我制作的《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/
开发者的游戏
在 indienova 站内可以访问:


暂无关于此文章的评论。