开发日志:游戏中的地图生成

作者:ICBITIC
2019-12-04
7 13 0

这是我制作的《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)

文中提到的网站

开发者的游戏

在 indienova 站内可以访问:

本文为用户投稿,不代表 indienova 观点。

近期点赞的会员

 分享这篇文章

ICBITIC 

初二学生 Endless Warfare开发者之一 

您可能还会对这些文章感兴趣

参与此文章的讨论

暂无关于此文章的评论。

您需要登录或者注册后才能发表评论

登录/注册