Come posso rilevare le "stanze" in un gioco a scorrimento laterale 2D?


24

Sto cercando di creare un sistema che riconosca determinati tipi di edifici e stanze che puoi creare nel gioco, come il modo in cui Terraria rileva "residenze". In quel gioco, una casa può essere costruita in un mondo basato su tessere costruendo una zona di blocchi che soddisfi una serie di condizioni:

  1. La zona è completamente isolata dall'esterno da blocchi posizionati dal giocatore.
  2. La zona può contenere un rettangolo 5x7.
  3. c'è almeno un tavolo, una fonte di luce e una sedia nell'area chiusa.
  4. C'è una porta che porta fuori dalla zona.
  5. Terraria ha sia uno strato di primo piano che uno sfondo. L'intero sfondo della zona deve essere riempito con blocchi posizionati dal giocatore.

Come posso rilevare in modo efficiente quando un giocatore ha costruito un'area di dimensioni adeguate e come posso verificare in modo efficiente che l'area contenga tutti i mobili / componenti richiesti?

Esempio di una zona interna che soddisfa tutti i requisiti abitativi:

inserisci qui la descrizione dell'immagine


5
Potresti elaborare? Cosa intendi per "tipi di costruzioni" e che cos'è una "residenza" in Terraria? Tieni presente che non tutti hanno giocato a quel gioco, concentrati anche su una domanda se vuoi che le persone ti aiutino e assicurati che la domanda abbia una risposta definita (non opinioni)
TomTsagk

1
Con tipi intendo diversi componenti / piastrelle utilizzati. La mia domanda è risolta di seguito. Cercherò di chiarire di più e di essere più specifico sulle domande future, grazie per l'aiuto.
Bernardo Becker,

1
A parte questo, assicurati che ci sia una differenza tra una stanza e una residenza . Il tuo elenco di proiettili suggerisce che li vedi come la stessa definizione. Usando la Terraria come esempio, i nemici non si generano nelle stanze, anche se non sono idonei come residenze (ad esempio mancando un tavolo, o solo 5x5 in dimensione)
Flater

Risposte:


37

Non ho familiarità con Terraria, ma questo può essere fatto facilmente usando un algoritmo di riempimento .

Invece di pixel, controlli i riquadri e, per ogni riquadro verificato, valuta se l'algoritmo può continuare a controllare altri riquadri, memorizzando in una matrice o in un elenco quali oggetti vengono trovati durante il processo.

L'algoritmo inizia nel riquadro in cui si trova il personaggio. Puoi iniziare ogni 1 secondo, 2 ... è una questione di ottimizzazione per trovare l'intervallo migliore.

È anche una buona idea impedire che l'algoritmo venga eseguito troppo a lungo, il che può essere ottenuto limitando il numero di riquadri che l'algoritmo può eseguire per corsa, altrimenti l'algoritmo causerà lunghi ritardi quando il personaggio si trova in un'area aperta.

modificare

Come indicato nei commenti, è possibile utilizzare altri approcci su quando avviare l'algoritmo, ad esempio quando il giocatore cambia una tessera o le tessere con una am I modified?variabile che, se true, avviano l'algoritmo. Tuttavia, devi stare attento con questo approccio:

  • Cosa succede se una tessera che fa parte della stanza, ma non una tessera in cui si trova il tuo personaggio, viene modificata? Forse la tessera è stata cambiata da un altro giocatore, o un evento ambientale, oppure la durata della tessera è terminata. Il tuo personaggio non sarà a conoscenza della modifica e non eseguirà l'algoritmo per rilevare la stanza aggiornata, una situazione soggetta a errori.

Potresti implementare una sorta di approccio per rilevare queste modifiche sulle tessere in cui il tuo personaggio non si trova, ma eseguire l'algoritmo a intervalli è l'approccio più semplice e meno soggetto a errori. Assicurati solo di non eseguire il flood-fill su ogni frame.

Fine della modifica


9
Perché non riempire solo le tessere "blocco piazzato dal giocatore"? Ciò potrebbe impedire o ridurre l'inondazione infinita di aree aperte (a condizione che le caverne / i palazzi non siano pieni di "blocchi posizionati dal giocatore").
jimbo1qaz,

20
Perché dovresti eseguirlo a intervalli fissi? Sicuramente puoi semplicemente eseguirlo quando viene posizionato un blocco (o distrutto, se applicabile, ed entrambi i casi possono essere probabilmente eseguiti in tempo costante ammortizzato per blocco) o quando si carica una particolare parte della mappa, quindi memorizzare il risultato da Là.
NotThatGuy

3
@immibis: sono abbastanza sicuro che Terraria non ti richieda di cambiare pavimento. Inoltre, non mi aspetto che un gioco cambi la sua stanza riconoscendo il comportamento in base a chi ha posizionato la tessera. Cosa succede se, ad esempio, costruisco una stanza adiacente a una scogliera?
Flater,

3
La terraria richiede di mettere pareti di fondo e non formerà una casa con sporcizia / roccia di fondo naturale. Controlla davvero solo i blocchi piazzati dal giocatore.
loa_in_

3
Per salvare la CPU, eseguivo l'algoritmo solo sulla modifica del blocco e quindi memorizzavo lo stato per ciascun blocco. Con questo, è un sempliceisRoom()
Herr Derb

3

Come ha detto @Ferreira da Selva, prova l'algoritmo di riempimento. Tuttavia, è possibile utilizzare alcuni criteri diversi quando si esegue l'algoritmo per determinare se è racchiuso.

Ad esempio, per ogni riquadro che controlli se è presente un riquadro di sfondo e, in caso contrario, sai che non è racchiuso. Oppure potresti far eseguire un'esecuzione differita separandola su un numero di frame, alleggerendo così il carico sul processore e riducendo il ritardo. Oppure potresti creare un limite di dimensioni della stanza a cui il giocatore dovrebbe attenersi.

L'uso di una combinazione di questi ti consentirebbe di farlo in modo più efficiente ed efficace.


3

Ci sono 2 problemi difficili nell'informatica. Nominare cose, invalidare la cache ed errori off-by-one.

Questo è un problema di invalidazione della cache.

Se hai un record di "is this inside", ogni volta che un blocco viene inserito o rimosso è abbastanza facile aggiornarlo e la sua regione tramite un riempimento.

Per ottimizzare questo, potresti voler avere una serie di livelli di "insidia".

Una "cella" è una regione circondata da blocchi posizionati dal giocatore (fino a una certa dimensione).

Una "stanza" è una cella con tessere di sfondo.

"Inside" è una stanza con una porta, una luce e una sedia.

Quando si posiziona un blocco in primo piano posizionato dal giocatore, fare una passeggiata in senso orario / antiorario per vedere se si forma una nuova cella. Quando rimuovi un blocco in primo piano posizionato dal giocatore, esamina se si rompe qualche cella - in tal caso, vedi se si forma una nuova cella unendo le due.

Quando una nuova cella viene formata o non formata, controlla che sia una stanza o un interno.

Le celle possono tenere traccia di quante tessere di sfondo hanno bisogno di essere una stanza. Quindi un semplice conteggio quando si forma una cella, una tessera di sfondo viene aggiunta o rimossa dalla cella, può determinare se si tratta di una stanza.

Allo stesso modo, le celle possono tenere traccia di quante sedie e fonti di luce (e in effetti oggetti di ogni tipo) sono al loro interno. Quindi il controllo interno è banale.

È inoltre possibile eseguire un conteggio degli ingressi.


Quindi aumentiamo la mappa con "celle". Quando le tessere vengono aggiunte o rimosse, controlliamo la cella della posizione e incrementiamo / diminuiamo il conteggio nella cella.

Utilizzare la camminata in senso orario / antiorario per definire l'interno e l'esterno di una cella quando viene aggiunto o rimosso un blocco di primo piano. Poiché le dimensioni delle celle sono limitate, questa camminata richiederà un numero limitato di passaggi.

Come bonus, ora hai un modo economico per parlare di stanze "opulanti", o "la stanza è benedetta da una fontana santa", o qualsiasi altra cosa su una stanza, poiché le stanze hanno un conteggio di ogni tipo di oggetto al loro interno. (Oppure, poiché le stanze hanno dimensioni limitate, basta eseguire un'iterazione; questo rimuove una cache).

Ogni posizione si trova al massimo in una cella, quindi puoi memorizzare l'id cella di ogni posizione sulla mappa principale.


0

Quando si utilizza l'algoritmo di riempimento flood, creare anche una variabile, che aumenterà con ogni casella selezionata, quindi se è superiore a 35 (7 * 5, la dimensione massima della stanza) si ferma semplicemente il controllo!


7 * 5 è il rettangolo di dimensioni minime che deve adattarsi all'interno della stanza
Rick
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.