Rallentamento delle prestazioni su un'implementazione A * in un gioco di difesa della torre


9

Sto realizzando un gioco di Tower Defense in Flash senza percorso predefinito.

Sebbene la mia griglia sia 40x40 (piccola?), A * è in difficoltà quando ricalcola ogni volta. Quindi ho apportato le mie modifiche per facilitare il ricalcolo e il conteggio delle celle toccate è sceso a circa 900 (quando si modifica vicino alla radice). Si blocca ancora per un periodo di tempo molto breve, ma rilevabile, quando viene posizionata una nuova torre.

È un problema di implementazione o 40x40 è troppo?

Modificare:

La struttura del mio codice:

  • Tutti i dati vengono salvati in 2d array di celle.
  • Ogni cella contiene il suo genitore nella direzione del percorso (1-8 in senso orario) e l'array con codifica bit a bit dei suoi figli nel percorso (ogni bit rappresenta un figlio).
  • La ricerca viene eseguita da A * con la stima della distanza euclidea.

Dovrai essere molto più specifico qui. Non abbiamo idea di come sia il tuo codice, di come sia strutturato, ecc., Quindi non possiamo trarre conclusioni su ciò che lo sta rallentando.
Sean James,

1
Quando ho implementato A * per l'ultima volta, ricordo che correva attraverso una griglia 64x64 al massimo a 1ms. Quindi sì, sembra essere un problema con la tua implementazione. Ti suggerisco di pubblicare il tuo codice o l'essenziale in modo che possiamo aiutarti ulteriormente.
Marc Müller,

Guarda la modifica che ho aggiunto
Dani,

1
Se 40x40 è troppo lento, è probabile che tu stia facendo qualcosa di molto sbagliato. Pubblica il tuo codice o profilalo. In alternativa, ingrandiscilo e vedi cosa succede: se una griglia 80x80 impiega più di quattro volte il tempo, hai qualcosa di estremamente rotto lì dentro.
Zorba THut,

Il titolo può essere un po 'più informativo, per favore?
tenpn,

Risposte:


4

Non posso commentare, ma primo profilo in Flex, tutto il resto è congettura.


Come posso profilare il progetto flash in flex?
Dani,

Sì e no. Non penso che carichi direttamente il progetto Flash. Penso che potresti essere in grado di profilare swf senza sorgente e ottenere comunque informazioni sul livello di funzione. Farei una ricerca su Google per "profiling di un progetto flash in flex" o simili. L'ho fatto e ottenuto questo: flexblog.edchipman.ca/… che sembra promettente.
Jonathan Fischoff il

Grazie, mi ha davvero aiutato a trovare la parte problematica (non era nell'algoritmo, vedi commento sulla domanda)
Dani

13

Suppongo che TD sia "Tower Defense"

Penso che A * stia andando un po 'fuori bordo per questo.

All'inizio del gioco, riempi l'area di gioco dai punti di uscita per creare una mappa di movimento:

 |---------|
 |5|4|3|3|3|
 |5|4|3|2|2|
->5|4|3|2|1->
 |5|4|3|2|2|
 |5|4|3|3|3|
 |---------|

e il movimento è sempre verso un quadrato con un valore inferiore.

Quando il giocatore piazza una torre, aggiorna ciascuno degli otto quadrati adiacenti: per ogni quadrato, imposta il suo valore di movimento su uno in più rispetto al valore adiacente più basso. Se il valore cambia, ripetere il processo centrato sul quadrato aggiornato. Quindi, per verificare che il percorso verso l'uscita non sia bloccato, assicurarsi che tutti i quadrati siano adiacenti a un quadrato di valore inferiore.

Quando il giocatore rimuove una torre, imposta il valore di movimento su uno in più rispetto al quadrato adiacente più basso e ripeti il ​​procedimento sopra.

Un approccio più semplice sarebbe quello di rifare il riempimento.


6
Ri-fare il riempimento di alluvione è più costoso che fare A * per un piccolo numero di unità - approssimativamente, la lunghezza della scheda - almeno in termini algoritmici (e poiché si tratta di Flash, le costanti non algoritmiche come il layout della memoria probabilmente possono " essere usato in modo molto efficace). Tuttavia, questo è un ottimo modello per molte unità comunicanti ed è chiamato diffusione collaborativa - scalablegamedesign.cs.colorado.edu/wiki/Collaborative_Diffusion .

@Joe Wreschnig: wow bel link. Ho usato quella tecnica prima ma non ho mai saputo come si chiamava. Grazie.
tenpn,

@Joe, fintanto che ci sono almeno alcune barriere nella mappa non penso che questo sarebbe più inefficiente che chiamare A *. Cioè, credo che solo per una mappa aperta, quasi senza barriere con poche unità potrebbe essere peggio.
edA-qa mort-ora-y

@edA: per definizione un alluvione deve eventualmente toccare ogni punto accessibile sulla mappa; Un * fornisce limiti superiori comprovati a quanti punti deve toccare, che è al massimo ogni punto accessibile sulla mappa e di solito molto meno. Il riempimento inondazione è un algoritmo più semplice per ottimizzare cose come il layout di memoria, ma come ho detto, in Flash che probabilmente non ha importanza.

@Joe, questo è quello che sto sostenendo è che anche con solo una manciata di torri, A * probabilmente toccherà quasi tutti gli spazi. Ma per N mostri deve solo superare total_squares / N per essere meno efficiente del riempimento dell'inondazione.
edA-qa mort-ora-y

2

Strano, pensavo di aver risposto, ma la risposta sembra essere sparita. Rendi il tuo algoritmo di ricerca in modo che possa essere aggiornato in più passaggi, in modo che quando posizioni una torre e riproduci un'animazione, puoi fare un po 'ogni fotogramma e avrai un punto tra mezzo secondo e un secondo per aggiornare il tuo A * senza una pausa evidente. È latenza: se non riesci ad accelerarlo, trova un modo per nasconderlo. Riprodurre un'animazione mentre si posiziona una torre sarebbe naturale per un gioco e sarebbe un buon posto per nasconderla.


Questa è una buona idea in generale, ma cattiva per questa domanda specifica. Un * su una griglia così piccola dovrebbe essere quasi istantaneo, senza richiedere una notevole quantità di tempo.
dav

Giusto. È l'unica risposta che potrei dare per risolvere il problema senza conoscere i dettagli dell'implementazione che potrebbero causare il rallentamento.
Kaj,

0

Per cominciare, è possibile modificare l'array in un vettore, che dovrebbe offrire alcuni miglioramenti della velocità. Pubblica il codice e potremmo essere in grado di suggerire ulteriori ottimizzazioni.


0

Immagino che il tuo rallentamento sia perché stai calcolando un percorso per tutti i personaggi contemporaneamente. Calcolare un percorso per un personaggio è veloce ma se ci sono due dozzine di personaggi nella scena, allora può impantanarsi.

Invece dovresti distribuire il carico su alcuni frame. Scaglionare i tuoi aggiornamenti AI in modo che personaggi diversi aggiornino il loro percorso su frame diversi. Sarebbe davvero evidente se un personaggio non reagisse fino a un secondo dopo, ma solo un fotogramma non causerà reazioni negative.


Questo è stato risposto quasi un anno fa ed è stato eliminato solo a causa del lavoro di montaggio di Grace. (Non aveva nulla a che fare con troppi personaggi.)

Grazie per avermi fatto sapere. Non ho notato le date.
jhocking
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.