ゲーム内でランダムに湖や川を生成するにはどうすればよいですか?


19

2Dブロックビルディングゲームがあり、ランダムに生成された湖や川を作ろうとしています。Perlinノイズアルゴリズムを調べましたが、ランダムで素晴らしい結果を生成することができませんでした。

私はpythonノイズライブラリを使用しようとしましたが、マップをあまりランダムに作成しませんでした。

よりランダムにするために、そのライブラリに欠けているシード関数がありますか?よりランダムにしたい場合、どの変数を変更しますか?可能であれば、数学と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

詳細をご覧ください。現在の状態では、この質問に答えることはできません。
グスタボマシエル

もう少し追加しましたが、何を知る必要がありますか。
ジュリアン

良い情報を追加しましたが、もう少し必要です。「それほどランダムではない」とは何ですか?私たちにスクリーンショットを撮ると、与えられた結果は何で、望んでいる結果は何ですか?どうやって試しましたか?あなたが私たちに見せるためのコードはありますか?あなたの文脈は何ですか?2Dまたは3D?タイルか多角形か?これがすべて多すぎる場合は申し訳ありませんが、私は助けようとしているだけです。-1は私のものではありませんでした。情報を提供しないと、質問はサイトに適さないものになり、サイトは閉じられます。繰り返しますが、私は助けようとしています。
グスタボマシエル

2
+1、今では良い質問です:)私はパーリンノイズとすべての手続き生成が苦手ですが、ランダムオブジェクトをシードしていますか?私が間違っていなければrandom.seed()、システム時間はシードとして使用されます。そして、octaves = random.randint(1,500000)*.000001+.5あなたが試す代わりに:(octaves = random.random() 同じ結果になり、0から1の間の数字が得られますが、500,000の数字よりもはるかに多くの可能性があります。)
グスタボマシエル

ありがとう+1 :) :)プラス1コメントしようとしましたが、できません
ジュリアン

回答:


7

まあ、それは思われるように、あなたは乱数ジェネレータをシードしていません。Pythonでは、random.seed()を使用するだけで簡単に実行できます。

また、1から500000の間の数値を生成し、0から1の間になるようにしていることもわかります。これは機能的な方法ですが、可能性は500,000に制限されています。あなたは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
質問で言及されているように、同じ出力を3回続けて取得している場合、ランダムジェネレーターをシードしていないためです。それをシードし、それが問題を解決するかどうかを確認します。
ashes999

ああ、「3回連続」ビットを見ていませんでした-「もっとランダムにするために、そのライブラリに欠けているシード関数があります」という部分を読んでいました。はい非繰り返しランダム:)のために播種
ティム・ホルト

8

これはあなたの特定のプログラミングの質問に答えているわけではありませんが、湖や川を作成することは、水滴と水片をランダムに配置することではないことを考慮してください。それは地形の高さ-湖に変わる窪地(流域)、およびより高い地点から低い地点に流れる水についてです。

あなたは理にかなっていること湖や川を作るの偉大な例をしたい場合、あなたはこのブログの記事をチェックアウトする可能性がある- > http://simblob.blogspot.com/2010/09/polygon-map-generation-part-1.html それはですあなたの目標が合理的に現実的な水路撮影である場合、この種のことの良いリファレンス。


2

非常に簡単です。同じマップを3回以上(またはそれ以上)取得している場合は、シードをランダム化していないためです。

これは何を意味するのでしょうか?

コンピューターは本質的に決定論的(非ランダム)であるため、ランダム性をシミュレートします。それは実際には繰り返しランダムです(だからこそ「疑似乱数ジェネレーター」と呼んでいます)。

これはどのように作動しますか?

乱数を作成するとき、「種」を与えるオプションがあります。重要なことは、常に同じシードを使用すると、常に同じ順序で同じ乱数シーケンスが得られることです。常に。これは良いことも悪いこともあります。

あなたの場合、あなたはランダムジェネレータをシードしていないように見え、デフォルトでは同じシードを取得しています-おそらくあなたの日付/時刻の一部のコンポーネントを使用しています。したがって、ランダム化することをお勧めします。

Gusatavoが答えで述べたように、random.seed()を呼び出す必要があります。ドキュメントには、「X [デフォルトパラメータ]が省略された場合None、または現在のシステム時間が使用された場合」と記載されています。これで十分です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.