如何在游戏中生成随机的湖泊和河流?


19

我有一个2D方块建筑游戏,正在尝试制作随机生成的湖泊和河流。我已经研究了Perlin噪声算法,但是无法获得它来生成随机且不错的结果。

我一直在尝试使用python noise库,但是它并不是随机创建地图。

我在该库中缺少一些种子函数来使其更加随机吗?如果我希望它变得更随机,该更改什么变量?如果可能的话,给我一个不太技术的答案,减少数学运算,增加更多python术语。

该地图是2D平铺的地图。这是其他算法的非随机性的一些示例。以下代码连续输出3次。我使用以下方法将八度和频率随机化:freq = 16.0 * random.randint(1, 500000) * 0.000001 + 0.5

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1
1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1
1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 1 1 1 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1
1 1 1 1 1 1 1 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1
1 1 1 1 1 1 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1
1 1 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1
1 1 1 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1

这是产生上面输出的代码:

"""Writes a 256x256 grayscale simplex noise texture file in pgm format
(see http://netpbm.sourceforge.net/doc/pgm.html)
"""
# $Id: 2dtexture.py 21 2008-05-21 07:52:29Z casey.duncan $

import sys
from noise import pnoise2
import random
octaves = random.randint(1, 500000) * 0.000001 + 0.5
freq = 16.0 * octaves
for y in range(30):
    for x in range(40):
        n = int(pnoise2(x/freq, y / freq, 1)*10+3)
        if n>=1:
            n=1
        else:
            n=0
        print n,
    print

请提供更多信息。在当前状态下无法回答此问题。
Gustavo Maciel

我增加了一点,但是,您需要知道什么。
朱利安

您添加了很好的信息,但我们还需要更多。什么是“不是很随机”?给我们的任何屏幕截图都可以看到给定的结果是什么,想要的结果是什么?您是如何尝试的?您有任何要显示给我们的代码吗?你的背景是什么?2D或3D?平铺还是多边形?抱歉,如果这一切都太多了,但我只是想提供帮助。-1不是我的,如果您不提供信息,该问题将不适合该网站,他们将关闭该网站。因此,我再次尝试提供帮助。
古斯塔沃·马歇尔

2
+1,现在是一个好问题:)我对Perlin杂讯和所有程序生成都不满意,但是,您是否为随机对象播种了?如果我没记错的话,random.seed()那么系统时间将用作种子。而且,octaves = random.randint(1,500000)*.000001+.5您可以尝试:(octaves = random.random() 得到相同的结果,您会得到一个介于0到1之间的数字,但它的可能性远不止500000个数字。)
Gustavo Maciel 2012年

谢谢+1 :) :)尝试加1条评论,但我不能
朱利安

Answers:


7

好吧,看来,您没有在播种随机数生成器。在python中,只需使用random.seed()即可轻松完成。

我也看到您正在生成一个介于1到500000之间的数字,并使它介于0到1之间。这是一种功能性方法,但是最多只能有500000种可能性。您最好只使用random.random()它已经生成了0到1之间的数字,但是可能性更大!如代码所示,如​​果仍然需要0.5到1.0之间的数字,则可以执行以下操作:(random.random() * 0.5) + 0.5

您的最终代码应如下所示:

import sys
from noise import pnoise2
import random
random.seed()
octaves = random.random()
# octaves = (random.random() * 0.5) + 0.5
freq = 16.0 * octaves
for y in range(30):
    for x in range(40):
        n = int(pnoise2(x/freq, y / freq, 1)*10+3)
        if n>=1:
            n=1
        else:
            n=0
        print n,
    print

就这样!


我不清楚播种与它有什么关系。如果您不播种,随机数仍然是随机的,但会重复。每次运行程序时,不播种的唯一症状应该是相同的随机序列(假设每次都使用相同的种子)。
蒂姆·霍尔特

1
如果您连续三次获得相同的输出(如您的问题所述),则很可能是因为您没有为随机生成器设定种子。给它播种,看看是否可以解决问题。
ashes999

啊,我没看过“连续3次”位-正在阅读,“该库中缺少某些种子函数,使其变得更加随机”。为非重复性随机播种:)
蒂姆·霍尔特

8

这不是在回答您的特定编程问题,而是要考虑创建湖泊和河流并不是要在它们之间随机放置一团水和一小段水。它与地形的高度有关-关于变成湖泊的洼地(盆地),以及从高处到低处的水流。

如果你想创建的湖泊和河流,使意义的一个很好的例子,你可以看看这个博客帖子- > http://simblob.blogspot.com/2010/09/polygon-map-generation-part-1.html 这是如果您的目标是相当现实的水文学,则可以为此类事情提供很好的参考。


2

这很简单:如果您连续三次(或多次)获得同一张地图,那是因为您没有随机化种子。

这是什么意思?

计算机本质上是确定性的(非随机),因此它们模拟随机性。它实际上是可重复的随机性(这就是为什么我们称其为“伪随机数生成器”)。

这是如何运作的?

创建随机数时,可以选择给它一个“种子”。重要的是,如果您始终使用相同的种子,则您将始终以相同的顺序获得相同的随机数序列。总是。这可能是好事或坏事。

在您的情况下,您似乎没有在随机生成器中植入种子,并且默认情况下,您会获得相同的种子-它可能使用了日期/时间的某些部分。因此,我建议您将其随机化。

正如Gusatavo在他的回答中提到的那样,您需要调用random.seed()。docs指出“如果省略X [默认参数]或None,则使用当前系统时间。” 这应该足够了。

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.