Wie kann ich zufällige Seen und Flüsse in meinem Spiel erzeugen?

19

Ich habe ein 2D-Blockbauspiel und versuche, zufällig erzeugte Seen und Flüsse zu erstellen. Ich habe mich mit dem Perlin-Rauschalgorithmus befasst, konnte jedoch keine zufälligen und schönen Ergebnisse erzielen.

Ich habe versucht, die Python-Rauschbibliothek zu verwenden , aber es wurden keine sehr zufälligen Karten erstellt.

Gibt es eine Seed-Funktion, die mir in dieser Bibliothek fehlt, um sie zufälliger zu machen? Welche Variable ändere ich, wenn ich will, dass sie zufälliger wird? Wenn möglich, geben Sie mir eine weniger technische Antwort mit weniger mathematischen und mehr Python-Begriffen.

Die Karte ist eine 2D-Kachelkarte. Hier sind einige Beispiele für die Nicht-Zufälligkeit des anderen Algorithmus. Der folgende Code wurde dreimal hintereinander ausgegeben. Ich habe die Oktaven und die Frequenz wie folgt randomisiert: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

Dies ist der Code, der die obige Ausgabe erzeugt hat:

"""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
julianisch
quelle
Weitere Infos bitte. Diese Frage kann im aktuellen Zustand nicht beantwortet werden.
Gustavo Maciel
Ich habe ein bisschen mehr hinzugefügt, aber was müssen Sie wissen.
Julian
Sie haben gute Informationen hinzugefügt, aber wir brauchen noch ein bisschen mehr. Was ist "nicht sehr zufällig"? Jeder Screenshot zeigt uns, was das gegebene Ergebnis ist und was das gewünschte Ergebnis ist. Wie hast du es versucht? Hast du einen Code, den du uns zeigen kannst? Was ist dein Kontext? 2D oder 3D? Gefliest oder polygonal? Tut mir leid, wenn das alles zu viel ist, aber ich versuche nur zu helfen. Die -1 gehörte nicht mir. Wenn Sie keine Informationen angeben, wird die Frage für die Site ungeeignet und sie wird geschlossen. Also wieder versuche ich zu helfen.
Gustavo Maciel
2
+1, jetzt ist es eine gute Frage :) Ich bin nicht gut mit Perlin-Rauschen und der gesamten prozeduralen Erzeugung, aber seedingst du das zufällige Objekt? Wenn ich mich nicht irre, wird random.seed()die Systemzeit als Startwert verwendet. Und anstatt octaves = random.randint(1,500000)*.000001+.5Sie versuchen können: octaves = random.random() (Es hat das gleiche Ergebnis, Sie erhalten eine Zahl zwischen 0 und 1, aber es gibt viel mehr Möglichkeiten als nur 500000 Zahlen.)
Gustavo Maciel
Danke +1 :) :) Versucht, plus 1 Kommentar, aber ich kann nicht
Julian

Antworten:

7

Nun, wie es scheint, Sie sind nicht Impfen den Zufallszahlengenerator. In Python kann dies einfach mit random.seed () durchgeführt werden .

Und ich kann auch sehen, dass Sie eine Zahl zwischen 1 und 500000 generieren und sie zwischen 0 und 1 machen. Es ist eine funktionale Methode, aber sie ist auf nur 500000 Möglichkeiten beschränkt. Du bist besser random.random(), wenn du es nur verwendest, es erzeugt bereits eine Zahl zwischen 0 und 1, aber mit viel mehr Möglichkeiten! Wenn Sie nach wie vor eine Zahl zwischen 0,5 und 1,0 benötigen, können Sie wie folgt vorgehen:(random.random() * 0.5) + 0.5

Ihr endgültiger Code sollte wie folgt aussehen:

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

Das ist alles!

Gustavo Maciel
quelle
Mir ist nicht klar, wie Seeding damit zu tun hat. Zufallszahlen sind immer noch zufällig, wenn Sie nicht setzen, sondern wiederholen. Das einzige Symptom für ein Nicht-Seeding sollte bei jedem Ausführen des Programms dieselbe zufällige Reihenfolge sein (vorausgesetzt, es wird jedes Mal dasselbe Seeding verwendet).
Tim Holt
1
Wenn Sie die gleiche Ausgabe dreimal hintereinander erhalten, wie in Ihrer Frage erwähnt, ist es sehr wahrscheinlich, dass Sie den Zufallsgenerator nicht gesetzt haben. Überprüfen Sie, ob das Problem behoben ist.
ashes999
Ah, ich hatte das "3-mal in einer Reihe" -Bit nicht gesehen - las, "Gibt es eine Seed-Funktion, die ich für diese Bibliothek vermisse, um sie zufälliger zu machen" -Teil. Ja Seeding für nicht wiederholte Zufälligkeit :)
Tim Holt
8

Dies ist keine Antwort auf Ihre spezielle Programmierfrage. Beachten Sie jedoch, dass es beim Erstellen von Seen und Flüssen nicht darum geht, zufällig Wasserflecken und -streifen dazwischen zu platzieren. Es geht um die Geländehöhe - um Vertiefungen (Becken), die sich in Seen verwandeln, und um Wasser, das von höheren zu niedrigeren Stellen fließt.

Wenn Sie ein großartiges Beispiel für die Schaffung von Seen und Flüssen suchen, das Sinn macht, lesen Sie diesen Blog-Beitrag -> http://simblob.blogspot.com/2010/09/polygon-map-generation-part-1.html Eine gute Referenz für diese Art von Dingen, wenn Ihr Ziel einigermaßen realistische Hydrographie ist.

Tim Holt
quelle
2

Es ist ganz einfach: Wenn Sie die gleiche Karte dreimal hintereinander (oder mehrmals hintereinander) erhalten, liegt dies daran, dass Sie den Startwert nicht zufällig ausgewählt haben.

Was bedeutet das?

Computer sind von Natur aus deterministisch (nicht zufällig) und simulieren daher Zufälligkeit. Es ist tatsächlich wiederholbar zufällig (deshalb nennen wir es "Pseudozufallszahlengenerator").

Wie funktioniert das?

Wenn Sie eine Zufallszahl erstellen, haben Sie die Möglichkeit, ihr einen "Startwert" zuzuweisen. Das Wichtigste ist , wenn man immer das gleiche Saatgut verwendet, werden Sie immer die gleiche Folge von Zufallszahlen erhalten, in der gleichen Reihenfolge. Immer. Das kann gut oder schlecht sein.

In Ihrem Fall sieht es so aus, als würden Sie den Zufallsgenerator nicht setzen, und standardmäßig erhalten Sie denselben Startwert - er verwendet wahrscheinlich eine Komponente Ihres Datums / Ihrer Uhrzeit. Daher empfehle ich Ihnen, es nach dem Zufallsprinzip zu ordnen.

Wie Gusatavo in seiner Antwort erwähnt hat, müssen Sie random.seed () aufrufen . In den Dokumenten heißt es: "Wenn X [der Standardparameter] weggelassen wird oder die Noneaktuelle Systemzeit verwendet wird." Dies sollte ausreichen.

ashes999
quelle