【问题标题】:Fall-off function for mountains山体衰减函数
【发布时间】:2026-01-03 11:00:01
【问题描述】:

我正在用体素地形编写类似 mincraft 的游戏。

对于山脉,我指定了位置、高度和大小。如果当前 (x, y, z) 坐标处的块是山的一部分,则有一个函数返回 True。如果一个块远离山的中心,只有当 z 坐标低于与山的距离的最大高度时才返回 True,即,块离山越远,最大高度越低。所以在山的中心,最大高度很高,即使z很高也会返回True(我使用的是z-up系统)。但是,离山越远,最大高度会越低。

但是,我当前的函数(如下)以线性方式返回它们,而真正的山脉没有直边:

def isMountain(self, x, y, z, mountainPos, mountainSize, mountainHeight):
        if math.hypot(mountainPos[0] - x, mountainPos[1] - y) < mountainSize:
                if z < (mountainHeight - math.hypot(mountainPos[0] - x, mountainPos[1] - y)):
                    return True
                else:
                    return False

第 3 行检查 z 是否小于该位置的最大高度,如果是,则返回 True,否则返回 False。

这些是距离的最大高度:
距离:最大高度
0 - 10
1 - 9
2 - 8
...
9 - 1
10 - 0

我如何重新编写此函数以使其返回更多类似山的值:不是线性的,而是立方或平滑衰减(如搅拌机比例编辑模式),因此它会给出更像这样的值:
0 - 10
1 - 9
2 - 9
3 - 8
4 - 7
5 - 5
6 - 3
7 - 1

【问题讨论】:

  • 如果在半径高于固定高度的范围内,为什么不考虑山内的方块?事实上,你如何确定现实生活中一座山的边界?另一种选择可以考虑提到的半径和某种坡度检查

标签: python terrain procedural-generation voxel


【解决方案1】:

您可以打破头脑找出一些数学公式,也可以模拟自然侵蚀过程。 这通常使用网格(矩阵、单元格...)和迭代来完成。 基本上你会从或多或少随机的高地开始,然后侵蚀它直到形成山脉,实际上山脉是剩下的。 也就是说,这通常比使用简单函数的成本更高,但在现代计算机上这会很好地工作。

另见:https://www.gamasutra.com/blogs/MattKlingensmith/20130811/198049/How_we_Generate_Terrain_in_DwarfCorp.php

【讨论】:

    【解决方案2】:

    如果您有兴趣走另一条路线,您可以使用修改后的柏林噪声版本来使用幅度和频率,然后使用平滑过渡来获得您想要的结果。您可以将点设置为具有一般高度范围,然后让噪声算法发挥作用来创建点之间的可变性。我已经做了类似的事情来创建一个具有不同生物群落的 inf gen 世界,这些生物群落具有不同的山高度和形状。

    【讨论】:

      【解决方案3】:

      也许你可以使用这样的反正切函数

      https://www.desmos.com/calculator/sn7tbepuxh

      其中 h 是最大高度,s 是陡度,x 是到峰中心的距离。最后的 -1 允许忽略负值,这样山的底部就不会永远延伸。

      我已经将它用于小型游戏的山生成器,它似乎工作正常,只要你调整你的陡度和高度值到山不是太尖。

      【讨论】: