Wie kann ich einen dauerhaften Status für Objekte implementieren, die in einer Ebene definiert sind?

17

Ich entwickle ein 2D-Metroidvania, das aus einer Reihe miteinander verbundener Ebenen besteht, die sich überarbeiten lassen.

Jedes Level wird durch eine gekachelte TMX- Datei dargestellt, in der ich angegeben habe, wo verschiedene Objekte verschiedener Sprite-Klassen erscheinen (z. B. Feinde, Pickups, Hebel usw.). Wenn ich ein neues Spiel starte, ein gespeichertes Spiel lade oder ein Level ändere, durchläuft meine Spieleschleife die entsprechende TMX-Datei und generiert alle Objekte in diesem Level.

Ich gehe mit Leveländerungen folgendermaßen um: Wenn das PlayerObjekt ein Objekt schneidet Portal, wird eine change_map()Methode aufgerufen, die eine neue Karte lädt (die dem geschnittenen Portal zugeordnete) und den Spieler an der entsprechenden Position auf der neuen Karte positioniert.

Einige meiner Objekte haben Staaten , die Ich mag würde sein persistent durch Pegeländerungen und speichern und das Spiel zu beenden. Wenn zum Beispiel ein Spieler eine Tür entriegelt und das Statusattribut der Tür auf "offen" gesetzt ist, möchte ich, dass die Tür offen ist, wenn der Spieler zurückkehrt. Ich möchte etwas Ähnliches für Hebel, die nach links oder rechts eingestellt werden können, und verschiedene andere Objekte. Außerdem hat der Spieler manchmal Gegenstände gesammelt, die ich nicht wieder herstellen möchte, wenn der Spieler den Bereich erneut besucht.

Meine Frage ist also, wie ich mit dieser Art von Beharrlichkeit umgehen kann.

Ich arbeite in Python, obwohl ich denke, dass Sie davon abstrahieren können.

GoldenGremlin
quelle

Antworten:

27

Ich denke, wenn Sie dieses Problem nicht überdenken, erzielen Sie die besten Ergebnisse. Deshalb implementiere ich ein einfaches System zum Speichern von Schlüsselwerten in Ihr Spiel, das Sie zusammen mit Ihren anderen Sicherungsdaten speichern und dann bei Bedarf laden, wenn Sie auf einen früheren Status zugreifen müssen.

Der Fluss könnte ungefähr so ​​aussehen:

  1. Ebene aus Datei laden
  2. Bevor Sie eine Kachel / ein Objekt platzieren, überprüfen Sie, ob es eine "dauerhafte" Eigenschaft hat.
    1. Wenn ja: Überprüfen Sie das gespeicherte Schlüssel-Wert-Paar auf den Schlüssel, der der Eigenschaft entspricht, und rufen Sie den entsprechenden Wert ab.
    2. Wenn nein: Platzieren Sie das Objekt wie gewohnt
  3. Wenn der Spieler das Level verlässt / speichert er die Spielschleife durch alle Objekte mit einer "dauerhaften" Eigenschaft und speichert sie als Schlüssel-Wert-Paar.

Hier ist ein Pseudocodebeispiel, das auf dem basiert, was ich für mein einfaches 2D-Spiel verwende:

def load_map(map):
    for y in range(0, height):
        for x in range(0, width):
            tile = map[x, y]

            for property in tile.properties:
                if is_persistent(property.name):
                    // Name prefixed with "persistent" means that it's persistent
                    // so we load the value from out persistent storage
                    property.value = persistent_values[property.name]

def save_map(map):
    ... everything in load_map ...
    if (property.name.matches("persistent_*")):
        // Name prefixed with "persistent" means that it's persistent
        // so we save the value to persistent storage
        persistent_values[property.name] = property.value

def is_persistent(name):
    return name.matches("persistent_*") and persistent_values.contains(name)

Dann kann ich mit dieser Eigenschaft einfach den Status überprüfen:

def draw():
    if properties["persistent_is_pressed"].value:
        draw_sprite(button_pressed)
    else:
        draw_sprite(button_unpressed)

def on_pressed():
    properties["persistent_is_pressed"].value = not properties["persistent_is_pressed"].value

Wenn Sie einen gekachelten Karteneditor wie Tiled verwenden, ist das Hinzufügen von Eigenschaften wie folgt ganz einfach:

Eigenschaft hinzufügen

Hoffentlich gibt Ihnen dies eine Idee, wie Sie einen dauerhaften Zustand so einfach wie möglich implementieren können!

Charanor
quelle
Dies ist sehr hilfreich, obwohl ich nicht genau weiß, wie ich es auf meine Situation anwenden kann. Ich werde noch etwas darüber nachdenken.
GoldenGremlin
Ich glaube, ich habe Probleme zu erkennen, wie ich die Speicherung der Werte zum Funktionieren bringen kann. Beim Speichern werde ich nicht über Kacheln in den TMX-Daten iterieren. Eher werde ich über Sprite-Objekte in meiner all_sprites-Gruppe iterieren. Wenn ich die Maps lade, verwende ich die TMX-Eigenschaften der TMX-Objekte als Parameter, wenn ich meine Sprite-Objekte instanziiere. Danach berühre ich diese Eigenschaften nicht mehr, sodass sie Änderungen in den Sprite-Objekten nicht mehr nachverfolgen.
GoldenGremlin
1
@dietestus Sie sollten Ihren Sprite-Objekten wahrscheinlich nur ein propertiesFeld geben, das Sie ändern, und die Kacheln nur propertiesals Hinweis auf die zu ändernde Eigenschaft verwenden (alle Daten werden jedoch in Ihrem Sprite gespeichert). Sie können die Kachel auch einfach an Ihr Sprite übergeben, damit Sie die Kachel aus dem Sprite ändern können :) Wenn nicht klar ist, was ich meine, kann ich noch mehr Pseudocode nachahmen
Charanor
3
@dietestus Sobald Sie mit einer dauerhaften Entität (Tür, Hebel) interagieren, speichern Sie den neuen Status in der Schlüsselwertzuordnung. Sie müssen beim Speichern nicht über die Karten iterieren, sondern haben bereits alles in Ihrer Karte.
Herr Derb
1
@dietestus Ja, das bist du :) Es ist ein einfaches Wörterbuch, in dem die Schlüssel Eigenschaftsnamen und die Werte (also ... Werte) sind. Wenn Sie mehrere Objekte auf derselben Kachel haben, ändert sich nichts, solange Sie eindeutige Schlüssel haben.
Charanor