You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Godot 3.6中制作双向循环的2D Simplex噪声地图?

解决2D无缝循环噪声地图的网格问题

问题原因分析

你当前的4D噪声输入方式直接导致了规则网格:

  • 代码中将x和y分别映射到独立的4D圆分量(cos(x*4)/sin(x*4) 与 cos(y*4)/sin(y*4)),这种独立映射会让噪声值在x和y的周期点上形成重复的网格规律——因为两个正交圆的特性,噪声会在(x,y)的周期网格处出现固定的高低点分布。
  • 你设置的x*4意味着x每90个单位完成一次360°循环,刚好与map_size=90完全匹配,这让整个地图的噪声周期与地图边界完全重合,进一步放大了网格的规律性。

解决方案:正确的环面映射

要生成全方向循环的无缝噪声,需要将2D坐标映射到4D空间的环面(Torus),让x和y的周期变化共同作用于4D向量,而非独立分开。具体修改如下:

extends Node

onready var tilemap_grass = get_node("/root/manager_global/manager_tile/tilemap_grass")
var map = {}
var noise = OpenSimplexNoise.new()
var map_size = Vector2(90, 90)
var cycle_scale = TAU  # 内置常量,等于2π,用于将坐标归一化到0-360°范围

func _ready():
    noise.seed = 14756107829
    noise.frequency = 0.6  # 控制噪声细节密度,可按需调整
    noise.octaves = 4      # 叠加多八度噪声,让地形更自然
    noise.persistence = 0.5  # 控制高八度噪声的权重,避免过于杂乱
    
    for x in range(map_size.x):
        for y in range(map_size.y):
            # 将x、y归一化为0到2π的角度值
            var u = (x / map_size.x) * cycle_scale
            var v = (y / map_size.y) * cycle_scale
            
            # 生成4D噪声输入:映射到环面的正确方式,确保坐标循环时4D向量回归初始值
            var noise_val = noise.get_noise_4d(
                cos(u), sin(u),
                cos(v), sin(v)
            )
            
            map[f"{x},{y}"] = noise_val
            
            if noise_val < 0:
                tilemap_grass.set_cell(x, y, 0)
    
    tilemap_grass.update_bitmask_region(Vector2(0, 0), map_size)

额外优化建议

  • 如果仍有轻微规律感,可适当提高frequency(比如1.0-2.0)或增加octaves(最多5-6,避免性能损耗)。
  • 去掉了原代码中多余的r偏移,直接使用cos/sin的结果即可,OpenSimplexNoise对输入范围无严格限制。
  • 验证无缝性:可以对比map["0,0"]与map["90,0"]、map["0,90"]的噪声值,应该基本一致,确保地图边缘能完美对接。

内容的提问来源于stack exchange,提问作者Thomas Blood

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 02:42:43