Pattern o framework per la risoluzione di input simultanei

1

Sto monitorando la posizione dei personaggi su una griglia 2D (questo è un gioco per computer). Ad ogni passo ogni personaggio può tentare di muoversi (stazionario, su, giù, sinistra o destra).

Ci sono alcune regole che governano quali mosse sono permesse. Esempio:

  • I personaggi non possono muoversi fuori dai confini della griglia.
  • I personaggi non possono passare l'uno durante l'altro durante lo spostamento.
  • I caratteri non possono spostarsi in quadrati che contengono un altro carattere.
  • Se due personaggi cercano di spostarsi nello stesso quadrato:
    • I caratteri che si spostano direttamente ricevono la priorità.
    • I personaggi che si spostano in diagonale verso il basso ottengono la 2a priorità.
    • I caratteri che si spostano orizzontalmente ottengono la 3a priorità ..
    • Etc.
  • Se due personaggi cercano di spostarsi nello stesso quadrato e nessuno dei due ha priorità, nessuno dei due può muoversi.

Quindi la natura di queste regole è che i movimenti del personaggio non possono essere applicati allo stato in sequenza, perché i movimenti di altri personaggi possono influenzare se sono in grado di muoversi o meno.

Sto trovando questo codice sorprendentemente complesso da scrivere. E questo mi riguarda perché farò

  • Vuoi estendere questo sistema in futuro per avere più regole.
  • È necessario creare sistemi simili in cui gli input devono essere risolti insieme ma dipendono l'uno dall'altro.

La mia domanda è. C'è un modello o una struttura che potrei applicare per semplificare o almeno standardizzare l'approccio per questo tipo di problema?

Se dovessi provare a dichiarare il problema in modo astratto, sarebbe: fare una modifica basata su regole a uno stato dato più input che, se elaborati in isolamento, porteranno a stati finali in conflitto.

    
posta Zach 17.12.2018 - 21:54
fonte

2 risposte

2

Potresti rappresentare le tue mosse intenzionali come un gruppo di aggiornamenti che sono alimentati attraverso una pipeline che costruisci esternamente. Ogni fase della pipeline decide se il batch è valido, valido con aggiustamenti (e li applica) o non valido (e genera un'eccezione).

Una fase applicherebbe le regole di confine, la fase successiva arresterebbe i personaggi che cercano di passare attraverso l'altro, la fase successiva risolverà i conflitti dello stesso quadrato e così via. Solo dopo aver risolto tutte le fasi della pipeline, trasferisci il batch corretto di aggiornamenti a una fase che applica tali aggiornamenti.

Una strategia di implementazione come questa ti offre l'isolamento e la modularità che cerchi, a scapito di fare più passaggi sull'elenco degli aggiornamenti. Se quella lista è piccola, potrebbe non essere un problema. Se la profilazione rivela che le prestazioni contano qui, potresti essere bloccato a fondere il tutto comunque. E in tal caso, il design più performante è il migliore.

    
risposta data 17.12.2018 - 22:12
fonte
0

Tratta non in movimento, come lo spostamento nella posizione corrente

Semplificare la logica di movimento per trattare non spostarsi come una forma di movimento piuttosto che un caso eccezionale, semplifica la vita.

Perché ora invece di dover verificare che un motore abbia lasciato il quadrato per primo, possiamo considerarlo solo come un'altra forma di collisione e applicare la logica di collisione per risolvere le controversie sulla proprietà della posizione.

Aggiungi semplicemente un'altra regola: a mover always has priority when moving to the same location it was already in .

Questo garantirà sempre una soluzione valida: No one moves .

Prova il Movimento a due stati

Ogni posizione della mappa ha due serie di stati: lo stato current e lo stato next .

Dopo ogni round di applicazione delle regole lo stato current diventa lo stato next e lo stato next diventa lo stato current . Questo è fatto facilmente usando due array e scambiando il puntatore con ciascuno.

Inoltre all'inizio di un round di regole di applicazione viene resettato lo stato next , (impostato su bianco / vuoto). Il ripristino all'inizio del round anziché alla fine consente all'IA del gioco di guardare lo stato next come stato history . Questo può essere utile per creare agenti AI adattivi.

Ora il calcolo dello stato di next può diventare molto più semplice. Hai accesso a un buono stato di current garantito. Lo stato next è solo una supposizione migliore dopo aver elaborato i primi K mover, che è vuoto quando K = 0. Il motore K + 1 può facilmente controllare la collisione controllando la cella desiderata nello stato next .

  • Se sono giorni felici vuoti.
  • Se non è vuoto, si è verificata una collisione e la proprietà dello spot è in questione.

    • Applica le regole di risoluzione delle collisioni. Questo metterà fuori gioco uno dei traslatori.
    • Determina la prossima mossa desiderata per il motore espulso.
    • Prova a spostarti nella nuova posizione, controllando se è vuoto per primo e applicando la logica di risoluzione delle collisioni, se non lo è.

Trasforma ogni mover nel mondo e risolvi ogni collisione mentre accade. Ora scambia le etichette di stato next e current e passa alla fase successiva dell'elaborazione.

    
risposta data 18.12.2018 - 01:16
fonte

Leggi altre domande sui tag