Come posso implementare lo stato persistente per gli oggetti definiti in un livello?


17

Sto sviluppando una Metroidvania 2D che consiste in una serie di livelli interconnessi che possono essere rivisitati.

Ogni livello è rappresentato da un file TMX piastrellato in cui ho specificato dove vengono generati vari oggetti di diverse classi di sprite (ad esempio nemici, pickup, leve, ecc.). Quando inizio una nuova partita, caricando una partita salvata o cambiando un livello, il mio ciclo di gioco scorre attraverso il file TMX appropriato e genera tutti gli oggetti in quel livello.

Gestisco i cambiamenti di livello nel modo seguente: Se l' Playeroggetto interseca un Portaloggetto, change_map()viene chiamato un metodo che carica una nuova mappa (quella associata al portale intersecato) e posiziona il giocatore nella posizione appropriata sulla nuova mappa.

Alcuni dei miei oggetti hanno stati che vorrei essere persistenti attraverso i cambiamenti di livello e il salvataggio e l'uscita dal gioco. Ad esempio, se un giocatore sblocca una porta e l'attributo di stato della porta è impostato su "aperto", vorrei che la porta fosse aperta quando il giocatore ritorna. Voglio qualcosa di simile per le leve, che può essere impostato a sinistra o a destra, e vari altri oggetti. Inoltre, a volte il giocatore avrà collezionato oggetti che non voglio rigenerare quando il giocatore rivisita l'area.

La mia domanda è quindi come posso gestire questo tipo di persistenza?

Sto lavorando in Python, anche se penso che tu possa sottrarti a questo.

Risposte:


27

Penso che non pensare troppo a questo problema fornirà i migliori risultati, quindi implementerei un semplice sistema di salvataggio del valore-chiave nel tuo gioco che memorizzi insieme agli altri dati di salvataggio e poi carichi su richiesta quando devi accedere a uno stato precedente.

Il flusso potrebbe assomigliare a questo:

  1. Carica livello da file
  2. Prima di posizionare una piastrella / oggetto verificare se ha una proprietà "persistente".
    1. Se sì: controlla la coppia chiave-valore salvata per la chiave corrispondente alla proprietà e recupera il valore appropriato.
    2. Se no: posizionare l'oggetto normalmente
  3. Quando il giocatore esce dal livello / salva il loop del gioco attraverso tutti gli oggetti con una proprietà "persistente" e li salva come coppia chiave-valore.

Ecco un esempio di pseudo-codice basato su ciò che uso per il mio semplice gioco 2D:

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)

Quindi posso solo controllare lo stato usando questa proprietà:

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

Se stai usando un editor di mappe affiancato come Affiancato, aggiungere proprietà come questa è molto semplice:

aggiunta di proprietà

Spero che questo ti dia un'idea di come implementare lo stato persistente il più semplice possibile!


Questo è molto utile, anche se faccio fatica a vedere esattamente come applicarlo alla mia situazione. Ci penserò ancora.
GoldenGremlin

Penso di avere problemi nel vedere come posso far funzionare il salvataggio dei valori. Durante il salvataggio, non eseguirò iterazioni sui riquadri nei dati TMX. Piuttosto, starò ripetendo gli oggetti sprite nel mio gruppo all_sprites. Quando carico le mappe, utilizzo le proprietà TMX degli oggetti TMX come parametri durante l'istanza dei miei oggetti sprite, ma successivamente non tocco tali proprietà, quindi non tengono traccia delle modifiche negli oggetti sprite.
GoldenGremlin

1
@dietestus Probabilmente dovresti semplicemente dare ai tuoi oggetti sprite un propertiescampo che modifichi invece e usare le tessere solo propertiescome indicazione di quale proprietà modificare (ma tutti i dati sono memorizzati nel tuo sprite). Potresti anche passare la tessera allo sprite in modo da poter modificare la tessera dallo sprite :) se non è chiaro cosa intendo, posso prendere in giro un altro pseudocodice
Charanor,

3
@dietestus Non appena interagisci con un'entità persistente (porta, leva), salvi il nuovo stato nella mappa dei valori-chiave. Non è necessario scorrere le mappe quando salvi, hai già tutto nella tua mappa.
Herr Derb,

1
@dietestus Sì, lo sei :) è un semplice dizionario in cui le chiavi sono nomi di proprietà e i valori sono (beh ... valori). Avere più oggetti sulla stessa tessera non cambierà nulla finché avrai chiavi univoche.
Charanor
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.