创造自己的世界 您所在的位置:网站首页 我的世界城市生成器 创造自己的世界

创造自己的世界

2024-04-13 10:00| 来源: 网络整理| 查看: 265

在上一篇专栏中我们讨论了群系和结构起始点的计算。这篇专栏将仔细讲解地形与洞穴生成。

一.与 1.18 的不同

由于上一篇专栏是在 1.18 写的而现在已经到 1.19 了,所以需要说明这个版本改了什么。总体而言,生成规律没有任何变化,最重要的变化其实是开放了配置这些生成的 API。

这个新的 API 叫做密度函数,它不仅包含了普通的噪声,还包含了其他计算,让地形生成更多样化。

在生成参数上,也发生了一点变化。不过这种变化不影响生成,只是换了个方式表达而已。下面是奇异性使用密度函数表达的例子(使用 https://misode.github.io/worldgen/density-function 生成):

具体的格式可以参考Wiki页面。

在密度函数中,有一类混合密度函数。它们的共同点是都以 blend 开头。对于你创建的新世界来说,这些密度函数是固定值:blend_offset 是 0、blend_alpha 是 1。而对于从旧版本升级而来的世界,这些混合密度函数就不是固定值了,它们会在过渡区块上起作用。在下文中,我们不会讨论新旧区块的过渡问题,因此这些函数将被视为固定值。

接下来就让我们正式开始讨论地形的生成。

二.地形偏移、深度与世界的高度

在上一篇专栏中,我们提过地形偏移和深度,这两个量有对应关系,简化之后像这样:

从这个公式,我们可以看出深度随 Y 值变低而升高。而对深度在水平方向上起作用的是地形偏移,地形偏移代表了地形上下起伏。

在公式上,地形偏移是一个三次样条函数,它使用了某一点的大陆性值、奇异性值、侵蚀度和山脊性值进行插值,得到最终的结果:

这个样条函数极度复杂,以 JSON 格式书写需要 1000 行左右,远远超出了本专栏可以解释的范围,所以在这里只讨论这几个参数对地形偏移的主要影响。

大陆性主要影响总体偏移,使偏移呈现阶梯状。

侵蚀度主要影响小幅度的偏移。

奇异性和山脊性主要影响河谷的形成。

由于地形偏移与 Y 值无关,而深度是在地形偏移的基础上加入了一个线性的 Y 参数,所以在水平方向上,起伏只与地形偏移有关,在任何高度下标准化后的图都应该相同。下图是指定种子下,Y=128 时的深度值图,数据经过标准化处理。

seed=514,region=[(0,64,0),(1024,64,1024)],大陆性噪声图等在上一篇专栏。清晰版本:https://sm.ms/image/dekqiXQ6n98Bp4G

深度不仅影响上篇专栏中讲过的群系放置,还影响接下来的不加粗糙度的原始密度值和最终密度值,主要影响它们的上部曲线,也就是地形最终的高度。一般来说,基础地形的最高点的深度值通常都在 0 左右,上下浮动不超过 0.3。但是深度不是影响地形高度的绝对因素,所以有的时候会产生较大的偏差,不过总体而言地形越高,地形偏移越大,同一高度上的深度也自然变大。

由于深度同时影响了群系和上部曲线,所以群系和地形高度是有一些联系的。最明显的就是:远古城市往往出现在高地形的地下,而海洋下基本不会出现深暗之域。深暗之域的放置要求是:深度大于 0.9 且侵蚀度小于 -0.225。而一个水平位置上至少存在一个深度大于 0.9 的垂直位置就要求基础地形高度至少在 52 格以上,再加上基岩层等的限制,基本上在基础地形高度 60 格以上地下才会出现深暗之域,所以海洋下能找到深暗之域是非常少的。而要生成远古城市,那么需要的高度就更高,所以高地形的地下才更容易出现远古城市,这是有着一定联系的。

三. 最终密度与基础方块放置

讲了这么多,那么洞穴之类的到底是怎么生成的呢?在讲解最终密度(N)之前,我们先介绍一下组成它的其他密度函数。

minecraft:overworld/caves/noodle

听名字就知道这个是生成面条洞穴的,主要生成细长封闭的洞穴,图像如下所示:

seed=514,region=[(0,320,0),(1024,-64,0)],未进行插值。红色标出的是小于0的部分。清晰版本https://sm.ms/image/JVN1YtbLyI2wBT3

minecraft:overworld/sloped_cheese

主要用于控制生成芝士洞穴的密度函数,和深度、粗糙度和地形因子都有关。

seed=514,region=[(0,320,0),(1024,-64,0)],未进行插值。绿线是值为0左右的点,红线是值为1.5625左右的点。清晰版本https://sm.ms/image/XAHmQuwiceVqhgo

minecraft:overworld/caves/entrances

用于控制洞穴与地面间进行连接的密度函数。

seed=514,region=[(0,320,0),(1024,-64,0)],未进行插值。红色表出的是小于0的部分。清晰版本https://sm.ms/image/EQ5thMfneA3bvWx

minecraft:overworld/caves/spaghetti_2d

控制意面洞穴是否进行生成。

seed=514,region=[(0,320,0),(1024,-64,0)],未进行插值。清晰版本https://sm.ms/image/RzluLU4g3TmkWvV

minecraft:overworld/caves/spaghetti_roughness_function

控制意面洞穴的形状。

seed=514,region=[(0,320,0),(1024,-64,0)],未进行插值。清晰版本https://sm.ms/image/8uyXHgCweUsjoxn

minecraft:overworld/caves/pillars

负责计算噪声柱。

seed=514,region=[(0,320,0),(1024,-64,0)],未进行插值。清晰版本https://sm.ms/image/tuTQ4gzC5x8Ofhl

最终密度值就是以上密度函数进行计算。为了简化公式,上述六个密度函数我们简记为 noodle(n)、cheese(c)、entrances(e)、spe2d(s_0)、speghetti(s_1)和 pillars(p)。

先来看看芝士洞穴、意面洞穴和噪声柱的生成,这三种计算基本是在一起的。

洞穴本质上分为两部分:与地上的连接口和在地下的空穴。为了分开这两个部分,最终密度中将 cheese 密度值小于 1.5625 的部分作为浅层地表和外界,大于 1.5625 的部分作为深层地下。浅层地表的密度值由 cheese 和 entrances 密度值决定,具体公式为:

在深层地下,洞穴的计算式为:

其中是 minecraft:cave_layer 噪声,是 minecraft:cave_cheese 噪声,这两个噪声也控制着芝士洞穴的位置。这个公式每一行都代表了一种洞穴类型:第一行是芝士洞穴,第二行是意面洞穴,第三行仍然是洞穴入口的函数。

但是这还没有结束,我们还没有生成噪声柱。如果 pillars 函数值不超过 0.3,则会被认为不能成为一个噪声柱,修正为 -1000000。经过这一步修正,现在的密度函数变成了:

与前面的表面函数组合,形成新的函数:

为了防止山过高和地下出现过深的芝士洞穴和意面洞穴,还需要进一步修改这个函数。具体来说,是对上下两部分进行钳制,具体做法是这样的:

从上述公式可以看出,超过 256 层密度值变为 -0.024994792 不变,低于 -40 层密度逐渐变为 0.037482421875。

到这里芝士洞穴、意面洞穴和噪声柱的生成就结束了。面条洞穴的生成要比这三个简单,仅需要 noodle 函数就可以。得到最终密度值为:

下面是最终密度值的图像:

seed=514,region=[(0,320,0),(1024,-64,0)],未进行插值。清晰版本https://sm.ms/image/yVU8w5cn4JTFkaf

使用红色标记这个图像中小于 0 的部分,得到下面的图像:

上图进行标记后的图像清晰版本https://sm.ms/image/vpqdVyGo6SBnLCs

可以看到在图像上方全部都小于 0,下方基本大于 0 但图像中间含有小于 0 的空洞。

最终密度值主要影响的是世界基础方块的放置,而放置与不放置的分界线就是 0。由于 256 层之上固定为 -0.024994792,所以 256 层以上不会有基础方块放置;地下 -40 层开始非面条洞穴密度逐渐增加,即在很低的高度下面条洞穴更主要。

可以看到上面的图像在边缘不怎么平滑,是因为没有进行插值。下面这张图像将最终密度值大于 0 的部分标记为白色,其他部分标记为黑色,并进行插值:

经过插值和二值化的图像清晰版本https://sm.ms/image/uHLJ2c3BzdqanCE

与实际生成进行对比,可以发现地形上确实差不多。但是有些在实际世界中生成的洞穴并没有在图中显示出来,这是因为洞穴生成不止有噪声洞穴,还有雕刻器洞穴。

在实际应用中,还有一个不带粗糙度的初始密度函数(AS),它是最终密度上部曲线的近似,分界线是 0.390625。它影响接下来的含水层放置和之后的地表规则。

不带粗糙度的初始密度函数图像,红色部分是值在0.390625附近的点。清晰版本https://sm.ms/image/IxaqGndy6bZMeA5四.含水层

在噪声洞穴中通常还包含有含水层,含水层是和基础方块一起生成的,且只生成于最终密度值小于 0 的地方。

含水层中的流体由 Aquifer.FluidPicker 提供,它唯一的实现是这样的:

从这段代码中可以看出,低于 -54 高度的含水层都必然是熔岩,高于 -54 且低于 63 则默认为水。

负责含水层计算的类是 Aquifer,它有两个实现:NoiseBasedAquifer 和 createDisabled。如果在世界设置里面关闭含水层,则默认调用 createDisabled,它的代码如下:

可以看出,即使关闭含水层也会进行放置流体,并且放置的特点是:-64~-55 层为熔岩,-54~63 层为水,再向上就没有含水层了。并且放置的所有流体都不会进行初始的流体更新。

如果开启含水层,则使用 NoiseBasedAquifer。它的代码比较复杂,这里将简单的说明一下它的做法。

如果此处最终密度大于 0,则不生成含水层。

如果高度小于 -54,则放置熔岩作为含水层。

barrier 控制压力值的计算,而压力值过大会阻止生成含水层。

fluid_level_floodedness 与 fluid_level_spread 控制地下含水层液面高度。

lava 控制是否使用熔岩充满含水层而不是水。如果此值绝对值大于 0.3,则使用熔岩。

如果生成时水在上方熔岩在下方,则液体一定进行更新。

下面是加入了含水层的地形生成。其中红色为熔岩,蓝色为水。

seed=514,region=[(0,320,0),(1024,-64,0)]。清晰版本https://sm.ms/image/n9VtiubZ6x7hONX五.矿脉

矿脉的生成也在初始地形生成时就已经生成,或者说它不属于地物。它优先于最终密度函数影响的放置。矿脉使用三个密度函数进行计算:

矿脉开关密度函数(vein_toggle)。当此值小于等于 0 时生成铁矿脉,大于 0 时生成铜矿脉。它的特点是:只在 Y 值 -60~51 时可能不为 0,其他高度都是 0。它不能完全决定矿脉的存在,如果不在矿脉的生成高度(铜 0~50,铁 -60~-8),则矿脉也不生成。

seed=514,region=[(0,320,0),(1024,-64,0)]。清晰版本https://sm.ms/image/cmhsYDH6VJuK1tC

上面的生成高度条件满足后,还需要计算是否合适进行矿脉方块放置。先计算当前点到要放置的矿脉的最大高度与最小高度的差值,取较小的一个,并钳制在 0~20 之间并映射到 -0.2~0 区间内。计算开关密度函数绝对值与这个映射值的和,如果小于 0.4,则也不生成矿脉方块。之后会再随机过滤掉30%方块,防止矿脉方块过多。

seed=514,region=[(0,320,0),(1024,-64,0)]。满足上述条件(不包含过滤30%方块的部分)的部分已标红。清晰版本https://sm.ms/image/VFn2PRQLTNOeGcf

第二个决定矿脉放置的是矿脉奇异密度函数(vein_ridged),类似于开关密度函数,它在 Y 不是 -60~51 的地方值为 -0.08。它进一步削减矿脉方块的数量。当此值大于 0 时,此处也被筛选掉不作为矿脉生成位置。剩下的位置将生成矿脉。

seed=514,region=[(0,320,0),(1024,-64,0)]。小于0的部分已标红。清晰版本https://sm.ms/image/yVN5lWCbjR8P4ZK

最后一个决定矿脉放置的是矿脉间隙密度函数(vein_gap)。它影响的是在矿脉中是否放置矿石或者矿物块。如果此值小于等于 -0.3,则会生成矿脉中的填充方块。紧接着再将开关密度的绝对值钳制在 0.4~0.6 并映射到 0.1~0.3,生成一个随机数,如果随机数小于映射值,则可以放置矿石(98%)或者矿物块(2%)。

seed=514,region=[(0,320,0),(1024,-64,0)]。小于-0.3的部分已标红。清晰版本https://sm.ms/image/LchO2aizkqrFlG5

接下来我们把矿脉也加入生成之中,现在我们的地形切面和真实生成已经很接近了:

seed=514,region=[(0,320,0),(1024,-64,0)]。清晰版本https://sm.ms/image/THVCMm3vsFryBo6

到这里,区块生成的 NOISE 阶段结束。

这篇专栏到这里就结束了,下篇专栏会介绍地表规则和地物放置。

源码来源:1.19.3,Mojang Mapping,反编译器 CFR 0.152,自动生成源码仓库 Nickid2018/GitMCDecomp(https://github.com/Nickid2018/GitMCDecomp)。

编写时长:3 周。

测试代码总行数:7669 行。

参考:

https://misode.github.io(misode 数据包生成器)

https://minecraft.fandom.com/zh(中文 Minecraft Wiki)

对文章有疑问或文章有错误可以在下方评论区指出。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有