Ich erstelle gerade ein Raumschiff-Erkundungsspiel und habe ein massives Problem, das ich seit Monaten zu lösen versucht habe. Der Rest meiner Gruppe hat sich entschieden, sich für ein Umschreiben zu entscheiden, um einige massive Spaghetti zu reparieren.
Wie auch immer, die Probleme gehen wie folgt vor:
Der Spieler beginnt in einem Raum, von dem aus er durch Türen zu anderen angrenzenden Räumen gelangen kann.
Diese Türen werden in einer Karte der Richtung, in der sie sich befinden, und des Türobjekts, auf das sie sich beziehen, gespeichert. Jedes Doorway-Objekt verfolgt die beiden Räume, die es verbindet, und leitet den Spieler bei Bedarf zu jedem.
Alle Räume müssen jedoch auf mindestens einem Weg zugänglich sein. Wenn Sie durch eine Tür auf der Steuerbordseite gehen, muss der andere Raum auf der Backbordseite dieselbe Tür haben. Ich kann das tun, indem ich einfach jede Wand als Tür habe, aber es wird langweilig, sie zu erkunden.
Das Vorgenerieren dieser Daten erwies sich als problematisch genug, um es zu scheitern, aber jetzt hat sich die Spezifikation geändert. Die Welt wird theoretisch unendlich sein, und als solche kann der Pfad nicht vorgeneriert werden, sondern muss stattdessen durchgeführt werden, wenn neue Räume benötigt werden oder voraussichtlich bald angefordert werden.
Ich muss also ein Labyrinth erzeugen, in dem Schleifen erlaubt sind, die quadratisch auf einem Raster gezeichnet sind, wobei nicht nur jeder Raum nicht direkt weiß, dass die anderen existieren, sondern auch voneinander zugänglich ist. Wenn Sie durch eine Tür auf einer Seite eines Raums gehen, muss sich dieselbe Tür auf der gegenüberliegenden Seite des nächsten Raums befinden.
Was ist ein guter Weg, um all diese Eigenschaften zu garantieren? Ich bin bereit, mich von Räumen zu trennen, die keine Kenntnis von anderen haben, würde es aber lieber so lassen, um den Raumtyp später leichter neu zu generieren, falls dies notwendig werden sollte.
Unten ist ein ASCII-Modell einer Textdatei eines 5x5-Beispiels, das ich erstellt habe. Https://pastebin.com/EtdAWAwD Linien sind Wände, Xs sind Türen und das S ist die Startposition des Spielers.
Jeder Rat wird geschätzt, auch auf alternativen Routen, die für die Erstellung dieser berücksichtigt werden müssen.
quelle
Antworten:
Es gibt viele Möglichkeiten, dies zu tun - es gibt sogar einen Wikipedia-Artikel darüber .
Das Googeln nach Dingen wie "Prims Algorithmus-Labyrinth", "Kruskals Algorithmus-Labyrinth" usw. führt zu einer Reihe von Beispielcodes und Youtube-Videos.
Für Ihre Anforderung, etwas zu benötigen, das auf eine unendliche Welt skaliert, ist die Methode der "rekursiven Unterteilung" meiner Meinung nach am einfachsten, obwohl es definitiv sichtbare Gitterausrichtungen gibt, wenn der Spieler auf die Karte schaut. Sie sollten in der Lage sein, die Lücken im Raster durch einen festen deterministischen Hash zu platzieren, damit Sie jedes Mal dasselbe Labyrinth an derselben Stelle neu generieren können.
quelle
Wenn Ihre Welt auf unbestimmte Zeit wachsen soll, helfen Ihnen der Prim-Algorithmus und der Kruslak-Algorithmus nicht weiter, da sie auf einem Feld bekannter Größe arbeiten.
Was Sie stattdessen tun können, ist, Ihr Labyrinth zu vergrößern, indem Sie mit einem einzelnen Raum beginnen und dann zufällig neue Räume an den Rand des Labyrinths anhängen. Sie tun dies, indem Sie einen zufälligen Raum auswählen, der noch freie Kanten hat, einen neuen Raum an dieser Kante erstellen und die beiden Räume mit einer Tür verbinden.
Dadurch entsteht ein Labyrinth mit einer baumförmigen Topologie mit dem ersten Raum als Wurzel. Wenn Sie möchten, dass das Labyrinth eine Schleife ausführen kann, können Sie einfach überprüfen, ob ein neu generierter Raum auch an andere Räume als den von ihm generierten angrenzt, eine Zufallszahl für jeden Raum würfeln und, wenn er hoch genug ist, auch eine Verbindung herstellen zu diesem Raum mit einer anderen Tür (wie viel "hoch genug" ist, hängt davon ab, wie viele Schleifen Sie möchten).
quelle
Sie könnten das versuchen:
Wann immer ein Raum generiert werden muss (z. B. in unmittelbarer Nähe
r
und noch nicht generiert)(x,y)
Finden Sie alle Türen zur 'Leere' im Radius
R
von(x,y)
(es kann in jedem Maße sein). Wenn keine gefunden wird, erstellen Sie eine Tür, die eine Verbindung zu herstellt(x, y)
erzeugen ein Labyrinth aus jeder Position in 1 gefunden beginnend, die ‚Lücke‘ in der gesamten Region des Radius Füllung
R
herum(x, y)
(durch irgendeinen Algorithmus, der gewährleistet Verbindung zwischen zwei beliebigen Punkten, so beispielsweise rekursive Backtracing). Wenn zu irgendeinem Zeitpunkt eine Tür zu einem Raum außerhalb des Radius erstellt wird,R
erstellen Sie die Tür, aber folgen Sie ihr nicht. (Sie generieren also effektiv eine ganze Region auf einmal anstelle eines einzelnen Raums.)Für die in 1. gefundenen Türen die Verbindung von beiden Seiten erzwingen.
Sie müssen
R
die Metrik empirisch auswählen und auswählen, was Sie benötigen. Es könnte sogar möglich sein, jedes Mal prozedural ein Begrenzungspolygon zu generieren (was recht einfach ist) und es als einschränkenden Bereich zu verwenden. Auf diese Weise wird der Generator unregelmäßiger.Ein Nachteil dieses Algorithmus besteht darin, dass die Form des Labyrinths von der Reihenfolge der Entdeckung abhängt, so dass es unmöglich ist, nur durch den Samen zu replizieren. Aber ich kann mir keine anderen Algorithmen vorstellen, die das erreichen, was nicht rein probabilistisch wäre.
Ich werde auch diesen Link https://nothings.org/gamedev/herringbone/ hier lassen, vielleicht kann es irgendwie nützlich sein.
quelle
Das erste ist, zu erkennen, dass es sich um ein Diagramm handelt. Da es sich in einem Raster befindet, bedeutet dies, dass jeder Knoten mindestens 4 Nachbarn hat.
quelle