巨大的程序产生的“荒野”世界


76

我敢肯定,大家都知道像《矮人要塞》这样的游戏-由程序产生的庞大荒野和土地。这样的东西,摘自这篇非常有用的文章。

但是,我想知道如何将其应用到更大的规模。我的世界的规模浮现在脑海(这不是地球表面大小的8倍吗?)。伪无限,我认为最好的术语是。

:D

这篇文章讨论了分形佩林噪声。我不是专家,但是我有一个大概的主意(它是某种随机产生的噪声,是半相干的,因此不仅仅是随机像素值)。

我可以按大小定义X的X区域,添加一些区域加载类型的东西,并产生一点噪声来生成一个区域。但这将导致大量的岛屿。

在另一个极端,我认为我真的不能产生出巨大的珀林噪声表。我认为,那将是一个大岛。

我很确定Perlin的噪音或某种噪音会以某种方式解决。我的意思是,该地图看起来非常好看。而且您可以用瓷砖替换ascii,并获得非常漂亮的外观。


9
“只会导致大量的岛屿”-或者,如果您只交换土地/水,它就会产生带有湖泊的土地。

3
即使这样,您也会以相当标准的模式得到大量的湖泊。
共产主义鸭子

3
@Kylotan:Mincraft的大小是无限的(不是真的,但是它确实很大...总体积= long.MaxValue x 128 x long.MaxValue)。因此,它不会一次生成整个世界,也不会将整个地图存储在内存中。如果尚未访问过16x128x16块的区域,则会异步生成这些区域,否则会从磁盘加载它们。
zfedoran

2
@The Communist Duck:是的,是的,像Minecraft这样的游戏可以在每个块上使用大约2到4字节的数据,但是在不再可见之后只需保存一个字节即可(一个字节描述了块的类型) ,其他字节描述照明和其他数据,稍后可以重新计算)。正如您提到的,在这里有趣的是,您可以使用RLE来将存储的大小大幅度减少到仅几个字节,因为这些块有些连贯。
zfedoran 2010年

4
“真的很大”与无限不同,您不能将两个术语互换使用。如果在发现地图时随时间增长地图,则地图的大小会随需求而增长-与无限地图完全不同。增长的每一点都可以根据需要生成。Minecraft中的地形数据非常容易进行小规模压缩,因为数据之间存在高度的连贯性。(例如,提到的RLE。)
Kylotan 2010年

Answers:


35

我想我会更好地理解您的要求。

噪声不是随机的-看起来是随机的,但完全基于数学公式并且可重复。所有信息都编码在公式中。这意味着您可以拥有一个可能覆盖无限区域的公式,而只需在所需区域的坐标上使用该公式即可。当需要相邻区域时,只需在新坐标上重新使用公式,由于公式会产生连续值,因此这些区域将无缝连接。

这是一个简化的示例,使用正弦代替perlin噪声生成高度,并且在X轴上想象世界是无限的,而在Y和Z轴上只有1个单位高。

公式为: height(x,y) = sin(x/20)

游戏开始,我们为附近区域生成高度。(0,0)至(9,0):

[0.0, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.34, 0.39, 0.43]

我们有一座小山,向右上升。假设我们走到了结尾,现在需要生成从(10,0到19,0)的值:

[0.48, 0.52, 0.56, 0.61, 0.64, 0.68, 0.72, 0.75, 0.78, 0.81]

请注意山丘如何稳定地上升,并且(10,0)的值与(9,0)的值很好地相符。这是因为正弦函数是连续的,这基本上意味着,如果将其输入2个相邻的数字,您将得到2个相邻的结果-对于相邻的特定定义。因此,如果您使用世界坐标作为定义世界的函数的参数,则无论您一次生成多少,都将得到一个连续的景观,该景观可以融合在一起。当您生成新零件时,它们的高度会自动从现有零件上继承下来,因为高度已经预先确定。

如果世界不会改变,那么您甚至不需要存储任何东西,因为您可以从公式中精确计算出给定点的高度。显然,使用Minecraft之类的世界是完全可变形的,因此在创建时只需保存每个块即可。鉴于相邻块之间具有高度的一致性(即,如果1个块是草,则其旁边的块也很有可能也是草),您可以非常有效地压缩数据-运行长度编码会起作用很好,但是几乎所有标准压缩算法都可以。

尽管我已经提到高度是最明显的值,但是您可以使用同一系统来生成所需的任何特征。使用具有连续属性的数学函数,其中输入是您的世界坐标,并且可以确定地标,矿床,产卵点的存在,无论您喜欢什么。(显然,一个公式中的值可能会影响另一个公式-将点煤放置在半空中是没有意义的,因此您可以生成世界高度图,然后仅计算距离地面足够远的区块的煤炭可能性。)


肯定,您已经帮助清理了一切,谢谢。:)但是像噪声函数之类的东西将不会连续。而且,如果连续不断,我将不会遇到“随机”世界。还是我在这里想念什么?
共产主义鸭子

抱歉,我有双重评论,但我认为以上内容与此分开。当您说“使用世界坐标作为Perlin噪声”时,这是否会与生成“巨大”噪声表一样,但有部分影响?我对今天的接受感到有点慢。
共产主义鸭子

好吧,您的噪声生成肯定可以连续,并且通常是连续的,因为您可以消除噪声。为了使边界更平滑,您可能需要稍微阅读一下边界,但是原理仍然相同。如果有问题的噪声需要伪随机数据,则可以从已知量生成该数据,即。世界坐标的哈​​希值。然后,输出是可预测的。
Kylotan

2
至于随机性,每个世界可以有自己的种子值,用于计算。例如。在上面的示例中,用sin(x + seed)代替sin(x)。每个不同的种子将产生一个不同的世界。关于庞大的工作表...我不确定这有什么意义。无论生成多少或何时生成,都没有关系。世界的初始状态由数学公式定义,您仅需使用该公式即可在需要时发现该状态。
Kylotan

32

我几年前写的本教程可能会给您一些您想要的东西:

替代文字

如果您在最后一步中进行了岛屿修改,那么它会趋向于未到达地图边缘的单个陆地。


7
出色的可视化!
zfedoran 2010年

3
我记得在做关于自然现象模拟的硕士论文时使用了本教程。我使用“山丘”示例在我的3D世界上创建了天空穹顶。很好的介绍了地形生成的概念。
C.McAtackney

1
疯了,太棒了!我不知道有人真正使用过它。
优厚的

1
我的天啊 !!!我在上一个项目中也使用了此方法……生成我所遇到的地形的最简单方法!!!
战争

15

要创建一个大岛,您无需一次全部生成。当您访问区域时,我将异步构建区域。

您可以做的一件事是,不用Perlin噪声倍频程波长来达到您想要的外观,而不是像文章中描述的那样使用遮罩来创建孤岛。通常,第一个八度表示地形的总体形状。它之后的所有八度音程都只会添加更多细微的细节。因此,请使用第一个八度音阶的波长来控制您的陆地量。如果您希望大陆块位于中心,则可以在远离中心移动时将高度图减小一定数量,然后对噪声进行归一化。例如,想象结合这两个来创建您的岛屿:

第一个八度 细节

本文应该会有所帮助:http : //freespace.virgin.net/hugo.elias/models/m_perlin.htm

如果您想了解无限的3D世界和各种技巧,可以通过玩噪声输入和输出来更改地形的外观,请查看本文:http : //http.developer.nvidia.com /GPUGems3/gpugems3_ch01.html

如果您不熟悉图形管道和着色器编程,可能会有点困难。


我想要实现的效果类似于Minecraft的地图的2d上下(不是游戏)……如果我只使用了较少的八度音阶,是否还不需要产生大量的Perlin噪声?还是我可以以某种方式生成非常少量的信息?
共产主义鸭子

我认为您可能仍然对Perlin噪音的工作原理有些困惑。您可以通过向函数发送针对Perlin噪声的x和y坐标偏移量来单独生成16x16块的块。注意PerlinNoise_2D(float x,float y)函数如何获取x和y坐标。换句话说,它会在某些(x,y)位置产生噪音。同样,生成更少的八度音阶与更改八度音阶的波长不同。更少的八度=>更少的细颗粒细节。较长波长=>更放大英寸
zfedoran

另外,这是一篇包含代码的文章,向您展示如何实现缩放/更长的波长:dreamincode.net/forums/topic/66480-perlin-noise
zfedoran 2010年


7

Perlin的喧闹声和朋友是一个很好的起点,但您可能希望将其进一步发展。大多数流行的基于噪声的生成器都会给您带来相当不有趣的结果。为了使地形逼真,您需要看一下模拟侵蚀效果的算法。矮人要塞(Dwarf Fortress)是目前世界上最先进的游戏化模拟器之一,它将侵蚀模拟作为建立世界的步骤之一。

我所见过的很酷的解决方案之一在Game Programming Gems 7中的“ Advanced Particle Deposition”一文中进行了描述。Internet上还有许多其他可用的方法,因此有很多资源可以借鉴(例如12) 。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.