Speichern von Wänden zwischen Fliesen

8

Ich schreibe eine isometrische Engine in C ++. Ich entschied mich für einen realistischeren Ansatz und ließ Wände zwischen zwei Kacheln Platz nehmen, nicht zwischen einer einzigen ganzen Kachel, wie im Bild unten gezeigt (genau wie in Die Sims).

konzeptionelle Grafik von dem, was ich erreichen möchte

Mein Problem ist, dass ich keine Ahnung habe, wie ich die Kachelkarten-bezogenen Daten in etwas speichern soll, das kein Raster ist. In dieser Situation muss ich es wohl A * -freundlich machen, damit es Knoten und Kanten zwischen Kacheln gibt, die nicht durch Wände getrennt sind. Hier ist ein weiteres Bild, das zeigt, was ich erreichen möchte:

Also hier ist die Frage (n):

Wie soll ich:

  • Speichern Sie die gesamte Karte, sowohl Kacheln als auch Wände
  • Optimieren Sie es für das Rendern
  • Verwenden Sie es für A * und andere Algorithmen, die in einem einfachen Raster recht einfach zu implementieren sind. Verwenden Sie jetzt Wände (Kanten), um Sichtbarkeit, Kollision usw. zu bestimmen.
Tchayen
quelle
Müssen Sie es aus verschiedenen Blickwinkeln betrachten können? Wenn ja, möchten Sie unterschiedliche Texturen auf gegenüberliegende Seiten derselben Wand anwenden? EG rosa Tapete auf der einen Seite, blau auf der anderen?
jzx
Ich brauche die Fähigkeit, die Karte zu drehen und verschiedene Arten von Farben und Materialien auf beiden Seiten der Wände zu verwenden. Jetzt denke ich, dass der obere Teil der Wand auch Material innerhalb der Wand zeigen sollte (z. B. Beton, Ziegel, Holz)
Tchayen

Antworten:

7

Ich beginne mit Koordinatensystemen - die Koordinaten für Gitterpositionen sind (x, y), aber wie Krom in einer anderen Antwort erwähnt hat, können für Wände bis zu zwei Wände für jede Gitterposition vorhanden sein. Dies führt zu einem zweiten Koordinatensystem für Kanten zwischen Kacheln . In diesem Artikel habe ich West und Süd verwendet, sodass die Kanten (x, y, West) oder (x, y, Süd) sein können, aber Sie können zwei auswählen, solange Sie konsistent sind.

Kantenkoordinaten für ein quadratisches Gitter

Diese beiden Koordinatensysteme (Gitterkacheln und Kanten) sind miteinander verbunden. Sie werden fragen wollen: welche vier Kanten umgeben eine Kachel?

Kanten, die eine Fliese umgeben

Für die Pfadfindung möchte A * wissen, welche Kacheln Nachbarn (B) der aktuellen Kachel (A) sind. Anstatt alle vier benachbarten Kacheln zurückzugeben, können Sie die vier Kanten überprüfen. Sie fügen Kachel B nur dann als Nachbarn hinzu, wenn zwischen A und B keine Wand vorhanden ist.

Anstatt zwei Wände für jede Kachel zu speichern, wie Krom vorschlägt, behalte ich die Wände normalerweise in einer separaten Datenstruktur: a Satz von Kantenkoordinaten. Wenn A * wissen möchte, ob B ein Nachbar von A ist, werde ich prüfen, ob diese Kante in der Menge enthalten ist. Wenn ja, dann gebe ich B nicht zurück.

Sie brauchen dies wahrscheinlich nicht für A *, aber für andere Dinge möchten Sie wahrscheinlich für jede Kante wissen, welche zwei Kacheln damit verbunden sind:

Fliesen, die eine Kante umgeben

Im Abschnitt „Algorithmen“ der Seite finden Sie die Berechnungen für diese beiden Operationen.

Beachten Sie auch: Bei einigen Kartentypen möchten Sie tatsächlich vier Kanten pro Gitterkachel speichern , damit Sie Einwegbewegungen unterstützen können.

amitp
quelle
4

In jeder Kachel können Sie Wände im Norden und Osten aufbewahren. Auf diese Weise muss jede Kachel nur noch 2 Boolesche Werte speichern (oder Ints, wenn Sie den Wandtyp speichern möchten). Der Nachteil ist, dass Kacheln entlang der Süd- und Westkanten keine Wände im Süden und Westen haben können, es sei denn, Sie fügen eine weitere Reihe versteckter Kacheln hinzu, die diese haben.

Kromster
quelle
2

In jeder Kachel können die Nachbarn (oder die Konnektivität) gespeichert werden, auf die sie Zugriff hat. Vielleicht als Bitmap. An den Wänden sind die beiden benachbarten Fliesen nicht miteinander verbunden. Dies ist sehr freundlich mit A *.

Der zweite Ansatz besteht darin, die Konnektivität der Kachel als Aufzählung zu speichern. Zum Beispiel ist eine vollständig geöffnete Kachel 0, eine Kachel mit Wand nach Norden und offener Rest ist 1, eine Kachel mit Wand nach Süden und offener Rest ist 2 usw., bis Sie alle möglichen Kombinationen abgedeckt haben.

user55564
quelle
Ich denke nicht, dass Ihr Kommentar "freundlich mit A *" wirklich zutrifft, da davon ausgegangen wird, dass die Schnittstelle ("Welche Kacheln sind benachbart?") Mit der Implementierung übereinstimmen muss ("Kacheln speichern Nachbarn"). Die beiden können unterschiedlich sein, wenn Sie beispielsweise eine separate Datenstruktur für Wände verwenden, wie von amitp vorgeschlagen.
Congusbongus
1

Hoffentlich ist dieses C # für dich in Ordnung - mein C ++ ist sehr rostig:

abstract class MapFeature
{
    public void Draw();
    public bool IsWall();
}
enum Direction
{
    North, South, East, West
}
class Wall : MapFeature
{
    public bool IsWall() { return true; }
    public Tile Front, Back; // Tiles on either side of the wall, otherwise null.

    #region Implementation of MapFeature

    public void Draw()
    {
        // Wall specific drawing code...
    }

    #endregion
}
class Tile : MapFeature
{
    public bool IsWall() { return false; }

    public MapFeature North, South, East, West; // Tiles/Walls on each side, otherwise null

    public bool CanGo(Direction direction)
    {
        switch (direction)
        {
            case Direction.North:
                return !North.IsWall();
            case Direction.South:
                return !South.IsWall();
            case Direction.East:
                return !East.IsWall();
            case Direction.West:
                return !West.IsWall();
            default:
                throw new ArgumentOutOfRangeException("direction");
        }
    }

    #region Implementation of MapFeature

    public void Draw()
    {
        // Tile specific drawing code...
    }

    #endregion
}

Sie können der Wall-Klasse wandspezifische Informationen hinzufügen, der Tile-Klasse kachelspezifische Informationen hinzufügen und die Bedingungen in der "CanGo" -Methode weiter verfeinern. Zum Beispiel, wenn eine Wand tatsächlich eine verschlossene Tür ist - beispielsweise eine Türklasse.

Um dies zu zeichnen, würden Sie mit einer beliebigen Kachel beginnen - beispielsweise der Kachel in der Mitte der aktuellen Kameraposition. Bewegen Sie sich dann entsprechend der Größe der Kacheln in Richtung und links von der Kamera. Führen Sie dann eine erste Durchquerung der IMapFeature-Knoten durch und zeichnen Sie jede Wand / Kachel in der angegebenen Reihenfolge.

A * funktioniert bei dieser Struktur, obwohl Sie offensichtlich einige Modifikationen benötigen würden, um so etwas wie verschlossene Türen zu handhaben.

Wenn Sie möchten, können Sie auch einen räumlichen Index der Kacheln beibehalten, der implizit die Wände enthält, um herauszufinden, welche Kacheln innerhalb der Kameragrenzen liegen.

Sie müssten immer noch nur ein Startplättchen und einen Abstand zum Durchqueren auswählen, basierend auf der Plättchengröße.

jzx
quelle