Wie erstellt man einen realistischen Fluss, ohne vorher die ganze Karte zu kennen?

Einleitung

Ich entwickle ein Echtzeitspiel mit dynamisch generierter Karte und möchte Flüsse hinzufügen, die von Bergen zum Meer führen.

Kurze Info zur Karte

Wenn sich in meinem Spiel ein Spieler an den Rand der aktuell erstellten Karte bewegt, werden neue Kartenstücke (kleine, quadratische Kartenstücke) auf den Server geladen. Wenn für den angeforderten Ort keine Chunks gefunden werden, werden sie mit demselben Startwert generiert, der in anderen Teilen der Karte verwendet wird. Derzeit gibt es keine Begrenzung der Kartengröße oder der Gesamtmenge der generierten Chunks. Ich verwende Perlin-Rauschen, um die Karte zu generieren. Ich behandle es als eine Höhenkarte, wobei jedes Feld eine Reihe von Werten hat, die es belegt, z. B. flaches Wasser beginnt von -0.12inklusive bis 0exklusiv.

Ich habe bereits darüber gelesen, wie man den Fluss realistisch aussehen lässt:

Frage

Wie füge ich der Karte Flüsse hinzu, wenn ich nicht weiß, wie die ganze Karte aussieht? Wenn ich nicht weiß, wo die Berge sind, kann ich die Quelle des Flusses nicht lokalisieren. Und wenn ich einen Teil der Karte bereits generiert habe, kann ich den Fluss nicht einfach etwas später hinzufügen, wenn ein Spieler auf eine Bergkette trifft.

Ähnlichkeiten

Ein ähnliches Szenario (glaube ich) ist in Minecraft. Auch dort wird die Karte generiert, wenn sich der Spieler mit einem Seed bewegt, und es gibt Flüsse, die weiter wirbeln, während die Karte weiter generiert wird. Leider kenne ich die dort verwendete Technik nicht.

Bildschirme aus dem Spiel

Geben Sie hier die Bildbeschreibung ein

Geben Sie hier die Bildbeschreibung ein

Das Laden von Chunks wurde vorübergehend deaktiviert, um die Grenzen anzuzeigen:

Geben Sie hier die Bildbeschreibung ein

Berücksichtigen neue Chunks die bereits generierten angrenzenden Chunks?
Nur zur Überprüfung: Wenn Sie Rauschen verwenden, um Gelände zu erzeugen, gibt es lokale Minima. Wasser neigt dazu, sich in diesen Minima anzusammeln, wenn sie in allen Richtungen minimal sind. Wasser wird auch über die unterste Lippe solcher Minima fließen. Ist das eine faire Darstellung dessen, wie Sie es tun? Unterscheiden Sie zwischen porösem und nicht porösem Boden oder zwischen Fels und leicht erodierbarem Boden?
@willk Derzeit nein, aber ich könnte sie während des Generierungsprozesses verfügbar machen. Allerdings mache ich mir ein bisschen Sorgen über mögliche Leistungskomplikationen solcher. Wenn sich der Spieler bewegt, wird mehr als ein Chunk geladen/erzeugt.
Okay, aber wenn Sie einen Chunk sagen, was ist die Auflösung innerhalb eines Chunks? Vermutlich muss es zwischen den Brocken eine gewisse Abstufung geben, oder es wird plötzliche Klippen oder Stürze entlang der Linien zwischen ihnen geben. Ich denke, wir brauchen viel mehr Klarheit über Ihren Algorithmus, um zu wissen, wie wir antworten sollen. Stammt das Bild von Ihrem Algorithmus?
PS Ist ein Chunk das ganze Bild oder ist es ein Rechteck innerhalb des Bildes? Können Sie für feinere Details in Rechtecke hineinzoomen?
@chasly-reinstateMonica Ja, ich könnte lokale Seen oder Teiche erstellen, aber ich folge nicht, wie man daraus einen Fluss erstellt. Ich unterscheide nicht zwischen porösem und nicht porösem Boden, auch nicht zwischen Fels und leicht erodierbarem Boden. Im Moment gehe ich davon aus, dass Wasser auf jedem Untergrund fließen kann. Die Blockgröße ist konfigurierbar, derzeit ist sie auf 15 x 15 Felder eingestellt. Ein einzelnes Feld ist ein 20x20-Pixel-Quadrat, das auf dem fraglichen Bild sichtbar ist, und ja, es stammt von meinem Algorithmus. Es gibt keine Klippen oder Abstufungen, die Verwendung des gleichen Samens hält alles schön konsistent. Das fragliche Bild hat etwa 3300 Felder mit 15 Chunks geladen.
Okay. Ich glaube, ich sehe das Problem. Sie gehen davon aus, dass der Wasserstand überall gleich ist. Dies gilt nicht für echtes Gelände, es sei denn, das Gelände ist vollständig porös. Mit nicht porösen Steinen haben Sie Pools, die hoch oben in den Bergen isoliert sind. Ihr Niveau wird weit über dem Meeresspiegel liegen. Was Sie finden müssen, sind Auslässe aus diesen höheren Pools. Diese führen zu niedrigeren Becken und so weiter bis hinunter zum Meeresspiegel. Das ist es, was die Flüsse gibt. Bin ich auf dem richtigen Weg?
Im Anschluss an @chasly wurde gesagt, Sie könnten eine andere (vielleicht kleinere - weniger Berechnung) Perlin-Rauschkarte erstellen, die sich auf den Wasserstand bezieht. Ihr übergeordneter Geländegenerator würde dann auf diese Wasserstandskarte verweisen, um die entsprechende In-/Exklusivregion zu berechnen.
Als ich das letzte Mal versucht habe, Welten zu erzeugen, habe ich eine Methode verwendet, bei der Perlin-Rausch-„Felder“ geschichtet wurden. Wie zum Beispiel Berg-/Ebenen-/Höhlenfelder, deren Werte, wenn sie einige Bedingungen erfüllen, die Form des Ganzen bestimmen würden. Die Felder hatten ihr eigenes Verhalten und sie interagierten alle untereinander. Bergfelder würden ermutigt, Pfaden zu folgen, die nominell linear oder subtil schlangenförmig waren. Bergfelder würden auch dazu neigen, die Werte niedrigerer Felder zu bestimmen. Sie würden nicht wollen, dass Täler entstehen, wo ein Berg war, also würden die Bergfelder sie magnetisch abstoßen und unterwerfen.
Ich denke, Minecraft generiert jetzt tatsächlich eine Karte mit geringen Details in großen Abschnitten. Es könnte also entscheiden "irgendwo durch diesen 128x128-Bereich fließt ein Fluss", und wenn es diesen Bereich tatsächlich generiert, entscheidet es genau, wo der Fluss platziert werden soll. Außerdem sind Minecraft-Flüsse eigentlich keine Flüsse, sie sind flach und können sich sogar im Kreis drehen.
Wenn Ihre Welt 2D ist, können Sie es sich mit ziemlicher Sicherheit leisten, eine riesige Menge im Voraus zu generieren, wie Dwarf Fortress.
Diese Frage hat nichts mit „Worldbuilding“ zu tun, es ist eine weitgereiste Frage im Game Engineering. Stellen Sie diese Frage einfach auf der ausgezeichneten Gamedev-Seite. (Oder googlen Sie einfach nach Hunderten von Diskussionen darüber.)

Antworten (4)

Das Problem ist wie gesagt unlösbar. Sie können am Ende einen Fluss erzeugen, den der Spieler bis zur Spitze eines kleinen Hügels mitten in einer Wüste zurückverfolgt.

Es gibt ein paar Alternativen, die dies zum Laufen bringen können:

LOD und Physik:

Sie können Perlin-Rauschen sub- und supersampeln, um Karten mit mehreren Auflösungen zu erstellen. Wenn Ihre Kacheln 1 Kachel pro 1 Meter sind, können Sie die gesamte Karte auf einer überschaubareren Ebene erstellen, sagen wir 1 Kachel pro 1 km, realistische Quellpunkte und einen groben Flusspfad berechnen und dann unterteilen, um zu sagen, 1 Kachel pro 100 m - Auf dieser Ebene wissen Sie, wo der Fluss mit einer Genauigkeit von 10 Kacheln fließt, finden heraus, wo der Fluss entlang dieses Pfades fließt, und dann, wo der Fluss rekursiv durch diese kleineren Kacheln fließt usw., bis Sie Ihre volle Detailebene erreicht haben.

Es ist besser, dies vorzuberechnen und wenn möglich zu speichern. Sie können dies immer noch bei Bedarf ausführen, aber es ist nicht einfach zu programmieren.

LOD und 1D-Perlin

Suchen Sie wie oben auf Ihrer Karte mit niedriger Auflösung den höchsten Punkt, von dem eine Quelle kommen würde, suchen Sie den nächsten Punkt auf Meereshöhe und zeichnen Sie eine gerade Linie. Verwenden Sie nun 1D-Perlin-Rauschen, um den Flusswind senkrecht zur Linie zu machen.

Dies ist viel einfacher zu programmieren - es kann einige unrealistische Artefakte enthalten, aber bei einem 2D-Kachelspiel wie diesem ist es unwahrscheinlich, dass Sie sie bemerken.

Fälsche es

Haben Sie 2 Arten von Flüssen. Einer geht "bergauf", einer "bergab". Erstellen Sie Kacheln, um den Fluss zu zeigen, der aus einer Quelle kommt und sich zu einem vollen Fluss formt, und eine, die einen vollen Fluss zeigt, der in ein kleines unterirdisches Merkmal abfließt.

Wenn der Perlin-Rauschwert für ein Küstengebiet ein sehr genauer Wert ist, dann erzeugt er einen "bergauf"-Fluss. Dies bewegt sich zum höchsten Kantenpunkt in der Kachel, der nicht an eine erkundete Kachel grenzt, die dann, wenn die nächste Kachel geladen wird, zum nächsthöheren Punkt geht. Wenn es erkennt, dass es zu einem lokalen Maximum gegangen ist (es gibt keinen höheren Punkt) oder alle benachbarten Kacheln bereits erkundet wurden, gehen Sie zurück bis etwa zur Mitte, legen Sie eine Kachel, die den Fluss zeigt, der aus einer Höhle oder Quelle oder etwas anderem unter der Erde kommt, also Der Benutzer sieht den Fluss nicht, der von der Spitze eines kleinen Hügels ausgeht.

Wenn der Perlin-Rauschwert für einen Berg ein sehr präziser Wert ist, dann erzeugt er einen "abwärts gerichteten" Fluss, folge ihm bis zur niedrigsten anderen Grenze einer unerforschten Kachel, und wenn er ein lokales Minimum erreicht, oder einen Brocken ohne unerforschte Nachbarn , lege ein Plättchen hinein, das den Fluss zeigt, der unter der Erde verschwindet.

Dies ist normalerweise gut genug für ein kachelbasiertes 2D-Spiel.

2 (oder mehr) Perlin-Kanäle

Derzeit führen Sie den Perlin-Generator einmal pro Kachel aus, um einen einzelnen Wert anzugeben. Ich würde vorschlagen, es mehrmals pro Kachel auszuführen (natürlich mit unterschiedlichen Startwerten und normalerweise unterschiedlichen Skalierungsfaktoren). Verwenden Sie diese mehreren Werte, um die Kacheln zu füllen, anstatt nur einen;

Dies kann dazu beitragen, die Erwartung zu brechen, dass Buchen neben Ebenen stehen, Ebenen normalerweise neben Wäldern, Wälder normalerweise neben Bergen usw.

Wenn Sie es zweimal ausführen, würde ich Feuchtigkeit und Höhe vorschlagen. Wenn Sie es dreimal ausführen, würde ich die Merkmalsgröße (Sand/Felsen, Eis/Schnee oder kahl -> Grasland -> Gestrüpp -> Bäume), Feuchtigkeit (Wüste -> fruchtbar -> Fluss -> Sumpf) und vorschlagen Höhe (Wasser -> Ebenen -> Hügel -> Berge). 4 mal würde vielleicht auch eine Temperatur beinhalten.

Anstatt sich darauf zu konzentrieren, Ihren Fluss „bergab“ zu laufen, versuchen Sie, ihn dort zu laufen, wo die Feuchtigkeit innerhalb eines bestimmten Konturbereichs liegt. Während der Fluss nicht "realistisch" bergab fließt, ist es in einem Fliesenspiel wie dem, was Sie anzeigen, verdeckt, Sie sind besser dran sicherzustellen, dass Bäume in der Nähe von Flüssen wachsen, Flüsse nicht von Wüste begrenzt sind und das Land in der Nähe von Flüssen ist fruchtbares Ackerland.

Obwohl diese Antwort bewundernswert ist, sollten die Frage und Antwort auf die Gamedev-Site verschoben werden. Das hat nichts mit "Worldbuilding" zu tun

Wie füge ich der Karte Flüsse hinzu, wenn ich nicht weiß, wie die ganze Karte aussieht? Wenn ich nicht weiß, wo die Berge sind, kann ich die Quelle des Flusses nicht lokalisieren. Und wenn ich einen Teil der Karte bereits generiert habe, kann ich den Fluss nicht einfach etwas später hinzufügen, wenn ein Spieler auf eine Bergkette trifft.

Sie können es nicht vollständig innerhalb eines Chunks tun. Wenn Sie sich am Rand eines Brockens befinden und es scheint, dass es ein lokales Minimum gibt, haben Sie zwei Möglichkeiten.

  1. Erweitern Sie das Terrain unsichtbar um das Minimum herum, bis Sie den Umfang dieses Minimums in dem noch unerforschten Stück finden. Sie müssen nicht den gesamten neuen Brocken vervollständigen, da Sie bis dahin wissen, wohin der Pool abfließen wird. Dies wird entweder zurück in den aktuellen Chunk oder irgendwo, noch unvollständig, in den noch nicht erforschten Chunk gehen. Mit anderen Worten, man muss über das Sichtbare/Erforschte hinausgehen. Man könnte das Just-in-Case -Programmierung nennen .

  2. Verwenden Sie einen deterministischen Algorithmus, der sich speziell mit dieser Eventualität befasst. Dh alle möglichen Ausgänge in den neuen Brocken absichtlich verschließen. Effektiv haben Sie einen Damm gebaut. Dies führt mit ziemlicher Sicherheit zu falsch aussehenden Artefakten.

Beachten Sie, dass die Verwendung lokaler Minima auf diese Weise (unter der Annahme von nicht durchlässigem Gelände) ermöglicht, dass die Körnung so fein ist, wie Sie es wünschen. Dadurch könnten Sie sogar Quellen und andere kleine Quellen des Flusses zeigen.

Vor einigen Jahren habe ich einen Algorithmus für ein RPG-Spiel geschrieben, der ähnlich funktionierte.
Denken Sie an "Minesweeper". Wenn Sie ein Bergquadrat entdecken, gibt es eine Wahrscheinlichkeit von ax%, dass es Wasser gibt. Aber dieses Quadrat beeinflusst die Wahrscheinlichkeit, dass der Brocken daneben ein Berg ist. Welche das Aussehen von Wasser beeinflussen. Für jede Karte können Sie Wasserquellen festlegen. Die Karte wird aus einem Bereich von 0-100 ausgewählt. Es ist die Menge an Wasserquellen. Je mehr die Karte unbeschattet ist, desto größer ist die Wahrscheinlichkeit, dass Wasser auftaucht.

Nun, um Ihnen zu helfen, kam die Natur mit diesem raffinierten Ding, dass Bäche auftauchen und dann in Risse sickern und verschwinden. Heutzutage können wir mit moderner Technologie verfolgen, wo es zurückkommt, aber in der "Entdeckungs"-Phase kann eine Quelle als 3 oder 4 verschiedene Bäche erscheinen. Sie müssen also keine durchgehende Linie von der entdeckten Quelle bis "irgendwo" sein. Es könnte nach 4 oder 5 Chunks enden.

Sie können also die durch Wasser erzeugten Brocken einfach beenden, wenn Spieler auf bereits entdeckte "trockene" Brocken treffen.
ODER

Erstellen Sie eine unterhaltsame Abwechslung in Ihrer Karte. Mit der Zeit (Bewegung des Spielers) wurden trockene Brocken nass, wenn der Generator versucht, die größte Wasserpfütze (falls niedriger) zu verbinden. Der Generator könnte auch die Wahrscheinlichkeit haben, einen Bach zu erzeugen, sodass er nicht geradeaus verläuft.

Denken Sie daran, dass sich Ihr Spieler wie ein typischer Mensch verhält. Sie könnten also Flussquellen entdecken, sie könnten in unentdeckte Regionen fließen, aber nur durch Scheidung und ihre Anwesenheit verändern sie, wie das Wasser fließt.

Der einfachste Algorithmus besteht darin, dass Flüsse immer dann in ein Bergtal "einrasten", wenn sich ein vorhandener Fluss innerhalb einer bestimmten Schwellenentfernung (und möglicherweise eines Winkels) zu einem Tal befindet, das die Mindestanforderungen erfüllt.

Nehmen wir an, Sie haben einen Fluss, der von einem beliebigen Algorithmus generiert wird, den Sie gerade verwenden. Es existiert noch keine Quelle und sie endet beim „Nebel des Krieges“ auf Ihrer Karte. Aber der Spieler bewegt sich, um das aufzudecken, und Sie verwenden den Algo, um die fehlenden Teile erneut zu generieren.

Angenommen, Ihr Algorithmus generiert gelegentlich Berge, wenn Berge/Täler innerhalb von n Einheiten vom "Ende" des Flusses und in einem Winkel von weniger als +/-45 Grad der Tangente des Flusses erstellt werden, dann generieren Sie daraus einen Flusspfad Zeige auf das Bergtal und platziere dort einen Gletscher.

Wenn der Endpunkt des Flusses weiter als n Einheiten entfernt ist, beginnen Sie, seinen Pfad zu generieren, und wenn dieser Pfad innerhalb von n Einheiten des Tals liegt, gehen Sie wie oben vor.

Es wäre notwendig, zuerst Berge zu erzeugen und dann den Fluss über eine solche Karte zu legen.

Sie könnten sogar zulassen, dass es sich mit mehreren Bergen / Tälern verbindet, wenn es mehrere potenzielle Standorte gibt, und dies würde Ihnen Nebenflüsse geben, die in einen Hauptfluss zum Meer münden.

Dies beruht natürlich auf einem zweiteiligen Kartengenerierungsschema, bei dem die meisten Kartenmerkmale generiert werden und Flüsse darauf "gemalt" werden. Es würde zum Beispiel für Minecraft funktionieren, von dem ich glaube, dass es das tut. Wenn Ihr Spiel ausgefeilter wäre und die Höhe verwenden würde, um die Pfade von Flüssen zu bestimmen, wäre dies unbrauchbar.