Wie kann ich "Räume" in einem 2D-Side-Scrolling-Spiel erkennen?


24

Ich möchte ein System entwickeln, das bestimmte Arten von Gebäuden und Räumen erkennt, die Sie im Spiel erstellen können, z. B. wie Terraria "Residenzen" erkennt. In diesem Spiel kann ein Haus in einer kachelbasierten Welt gebaut werden, indem eine Zone mit Blöcken erstellt wird, die eine Reihe von Bedingungen erfüllen:

  1. Die Zone ist durch vom Spieler platzierte Blöcke vollständig von "außen" isoliert.
  2. Die Zone kann in ein 5x7-Rechteck passen.
  3. In dem geschlossenen Bereich befindet sich mindestens ein Tisch, eine Lichtquelle und ein Stuhl.
  4. Aus der Zone führt eine Tür heraus.
  5. Terraria hat sowohl eine Vordergrund- als auch eine Hintergrundkachelebene. Der gesamte Hintergrund der Zone muss mit vom Spieler platzierten Blöcken gefüllt sein.

Wie kann ich effizient erkennen, wenn ein Spieler einen Bereich mit angemessener Größe erstellt hat, und wie kann ich effizient überprüfen, ob der Bereich alle erforderlichen Möbel / Komponenten enthält?

Beispiel einer Innenzone, die alle Wohnanforderungen erfüllt:

Bildbeschreibung hier eingeben


5
Könnten Sie näher darauf eingehen? Was meinen Sie mit "Bautypen" und was ist ein "Wohnsitz" in Terraria? Denken Sie daran, dass nicht jeder dieses Spiel gespielt hat, konzentrieren Sie sich auch auf eine Frage, wenn Sie möchten, dass die Leute helfen, und stellen Sie sicher, dass diese Frage eine eindeutige Antwort hat (keine Meinungen)
TomTsagk

1
Mit Typen meine ich verschiedene verwendete Bauteile / Fliesen. Meine Frage ist unten gelöst. Ich werde versuchen, ausführlicher auf zukünftige Fragen einzugehen, danke für die Hilfe.
Bernardo Becker

1
Stellen Sie außerdem sicher, dass es einen Unterschied zwischen einem Zimmer und einer Residenz gibt . Aus Ihrer Aufzählungsliste geht hervor, dass Sie sie als dieselbe Definition ansehen. Am Beispiel von Terraria laichen Feinde nicht in Räumen, auch wenn sie nicht als Residenzen zugelassen sind (z. B. Fehlen eines Tisches oder nur 5x5 in der Dimension)
Flater

Antworten:


37

Ich kenne Terraria nicht, aber das kann einfach mit einem Flood-Fill-Algorithmus gemacht werden .

Anstelle von Pixeln überprüfen Sie die Kacheln und bewerten für jede überprüfte Kachel, ob der Algorithmus andere Kacheln überprüfen kann, während Sie in einem Array oder einer Liste speichern, welche Objekte während des Vorgangs gefunden werden.

Der Algorithmus beginnt bei der Kachel, auf der sich das Zeichen befindet. Sie können jede Sekunde beginnen, 2 ... es ist eine Frage der Feinabstimmung, um das beste Intervall zu finden.

Es ist auch eine gute Idee, zu verhindern, dass der Algorithmus zu lange ausgeführt wird. Dies kann erreicht werden, indem die Anzahl der Kacheln begrenzt wird, die der Algorithmus pro Lauf ausführen kann. Andernfalls führt Ihr Algorithmus zu langen Verzögerungen, wenn sich der Charakter in einem offenen Bereich befindet.

Bearbeiten

Wie in den Kommentaren angegeben, können Sie andere Ansätze verwenden, um den Algorithmus zu starten, z. B. wenn der Spieler ein Plättchen ändert oder am I modified?wenn die Plättchen eine Variable haben true, mit der der Algorithmus gestartet wird. Sie müssen jedoch mit diesem Ansatz vorsichtig sein:

  • Was passiert, wenn ein Plättchen, das Teil des Raums ist, aber kein Plättchen, auf dem sich Ihr Charakter befindet, geändert wird? Möglicherweise wurde das Plättchen von einem anderen Spieler oder einem Umgebungsereignis geändert, oder die Lebensdauer des Plättchens ist abgelaufen. Dein Charakter wird die Änderung nicht bemerken und den Algorithmus nicht ausführen, um den aktualisierten Raum zu erkennen, eine fehleranfällige Situation.

Sie könnten einen Ansatz implementieren, um diese Änderungen auf Kacheln zu erkennen, auf denen sich Ihr Charakter nicht befindet. Die Ausführung des Algorithmus in Intervallen ist jedoch der einfachste und weniger fehleranfällige Ansatz. Stellen Sie einfach sicher, dass das Füllen nicht bei jedem Frame ausgeführt wird.

Ende der Bearbeitung


9
Warum nicht nur zwischen "vom Spieler platzierten Block" -Fliesen füllen? Dies könnte eine unendliche Überflutung offener Gebiete verhindern oder verringern (solange Höhlen / Villen nicht mit "vom Spieler platzierten Blöcken" gefüllt sind).
Jimbo1qaz

20
Warum sollten Sie dies in einem festen Intervall ausführen? Sicherlich können Sie es einfach ausführen, wenn ein Block platziert wird (oder, falls zutreffend, zerstört wird, und beide Fälle können wahrscheinlich in amortisierter konstanter Zeit pro Block ausgeführt werden) oder wenn Sie einen bestimmten Teil der Karte laden und dann das Ergebnis von speichern Dort.
NotThatGuy

3
@immibis: Ich bin mir ziemlich sicher, dass Terraria nicht verlangt, dass Sie den Boden wechseln. Ich würde auch nicht erwarten, dass ein Spiel das Raumerkennungsverhalten ändert, basierend darauf, wer das Plättchen platziert hat. Was ist, wenn ich zB einen Raum neben einer Klippe baue?
Flater

3
Terraria erfordert, dass man Hintergrundwände setzt und kein Haus mit natürlichem Hintergrundschmutz / -felsen bildet. Es werden wirklich nur vom Spieler platzierte Blöcke geprüft.
Loa_in_

3
Um CPU zu sparen, würde ich den Algorithmus nur beim Blockwechsel ausführen und dann den Status für jeden Block speichern. Mit diesem ist es eine einfacheisRoom()
Herr Derb

3

Probieren Sie, wie @Ferreira da Selva sagte, den Flood-Fill-Algorithmus aus. Sie können beim Ausführen des Algorithmus jedoch verschiedene Kriterien verwenden, um zu bestimmen, ob er eingeschlossen ist.

Beispielsweise überprüfen Sie für jede Kachel, ob eine Hintergrundkachel vorhanden ist, und wenn dies nicht der Fall ist, wissen Sie, dass sie nicht eingeschlossen ist. Oder Sie können eine verzögerte Ausführung veranlassen, indem Sie die Ausführung auf mehrere Frames verteilen, wodurch der Prozessor entlastet und die Verzögerung verringert wird. Oder Sie können eine Raumgrößenbeschränkung festlegen, die der Player einhalten muss.

Wenn Sie eine Kombination dieser Methoden verwenden, können Sie dies effizienter und effektiver durchführen.


3

In der Informatik gibt es zwei schwierige Probleme. Benennen von Dingen, Ungültigmachen des Cache und Fehler nach dem anderen.

Dies ist ein Cache-Invalidierungsproblem.

Wenn Sie eine Aufzeichnung von "Ist dies in" haben, ist es ziemlich einfach, einen Block und seine Region über eine Überflutungsfüllung zu aktualisieren, wenn er platziert oder entfernt wird.

Um dies zu optimieren, möchten Sie möglicherweise eine Reihe von Stufen der "Insidenz" haben.

Eine "Zelle" ist eine Region, die von vom Spieler platzierten Blöcken (bis zu einer bestimmten Größe) umgeben ist.

Ein "Raum" ist eine Zelle mit Hintergrundkacheln.

"Inside" ist ein Raum mit einer Tür, einem Licht und einem Stuhl.

Wenn Sie einen vom Spieler platzierten Vordergrundblock platzieren, gehen Sie im / gegen den Uhrzeigersinn, um festzustellen, ob eine neue Zelle gebildet wird. Wenn Sie einen vom Spieler platzierten Vordergrundblock entfernen, prüfen Sie, ob er Zellen beschädigt. Wenn dies der Fall ist, prüfen Sie, ob durch Zusammenführen der beiden Zellen eine neue Zelle entsteht.

Wenn eine neue Zelle geformt oder nicht geformt ist, prüfen Sie, ob es sich um einen Raum oder ein Inneres handelt.

Zellen können verfolgen, wie viele Hintergrundkacheln sie benötigen, um einen Raum zu bilden. Wenn dann eine Zelle gebildet wird, eine Hintergrundkachel hinzugefügt oder aus der Zelle entfernt wird, kann eine einfache Zählung bestimmen, ob es sich um einen Raum handelt.

Ebenso kann Cells verfolgen, wie viele Stühle und Lichtquellen (und tatsächlich Objekte aller Art) sich in ihnen befinden. Dann ist der Insider-Check trivial.

Eine Zählung der Zugänge ist ebenfalls möglich.


Also erweitern wir die Karte mit "Zellen". Wenn Kacheln hinzugefügt oder entfernt werden, überprüfen wir die Zelle der Position und erhöhen / verringern die Anzahl in der Zelle.

Verwenden Sie das Gehen im / gegen den Uhrzeigersinn, um das Innere und Äußere einer Zelle zu definieren, wenn ein Vordergrundblock hinzugefügt oder entfernt wird. Da die Größe der Zellen begrenzt ist, ist die Anzahl dieser Schritte begrenzt.

Als Bonus haben Sie jetzt eine günstige Möglichkeit, über "opulente" Räume zu sprechen, oder über "Raum ist durch einen heiligen Brunnen gesegnet", oder irgendetwas anderes über einen Raum, da in Räumen die Anzahl der einzelnen Objekttypen angegeben ist. (Da die Größe der Räume begrenzt ist, müssen Sie nur eine Iteration durchführen. Dadurch wird ein Cache entfernt.)

Jeder Standort befindet sich in höchstens einer Zelle, sodass Sie die Zellen-ID jedes Standorts auf der Hauptkarte speichern können.


0

Wenn Sie den Flutfüllungsalgorithmus verwenden, erstellen Sie auch eine Variable, die mit jedem aktivierten Kachel erhöht wird. Wenn sie also größer als 35 (7 * 5, die maximale Größe des Raums) ist, wird die Überprüfung einfach abgebrochen!


7 * 5 ist das kleinste Rechteck, das in den Raum passen muss
Rick
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.