Un * percorso di ricerca mesh mesh


15

Quindi ho realizzato questo gioco java 2D top down in questo framework chiamato Greenfoot e ho lavorato sull'intelligenza artificiale per i ragazzi che combatterai. Voglio che siano in grado di muoversi realisticamente in tutto il mondo, così presto ho capito, tra un paio di altre cose, avrei bisogno di un qualche tipo di tracciamento.

Ho realizzato due prototipi A *. Uno è basato sulla griglia e poi ne ho creato uno che funziona waypoint, quindi ora ho bisogno di trovare un modo per passare da una "mappa" 2D degli ostacoli / edifici a un grafico di nodi da cui posso tracciare un percorso. L'individuazione del percorso reale sembra soddisfacente, solo i miei elenchi aperti e chiusi potrebbero utilizzare una struttura di dati più efficiente, ma ci arriverò se e quando ne avrò bisogno.

Intendo utilizzare una mesh di navigazione per tutte le ragioni delineate in questo post su ai-blog.net . Tuttavia, il problema che ho affrontato è che quello che A * pensa sia il percorso più breve dai centri / spigoli poligonali non è necessariamente il percorso più breve se viaggi attraverso qualsiasi parte del nodo. Per avere un'idea migliore puoi vedere la domanda che ho posto su StackOverflow .

Ho una buona risposta riguardo un grafico di visibilità. Da allora ho acquistato il libro ( Geometria computazionale: algoritmi e applicazioni ) e ho approfondito l'argomento, tuttavia sono ancora a favore di una rete di navigazione (vedi " Gestione della complessità " dalle Note di Amit sulla ricerca di percorsi ). (Come nota a margine, forse potrei usare Theta * per convertire più waypoint in una linea retta se il primo e l'ultimo non sono oscurati. O ogni volta che torno indietro, controlla il waypoint prima dell'ultimo per vedere se posso andare direttamente da che a questo)

Quindi sostanzialmente quello che voglio è una mesh di navigazione in cui una volta che l'ho passato attraverso un algoritmo a imbuto (ad esempio questo da Digesting Duck ) otterrò il vero percorso più breve, piuttosto che uno che è il percorso più breve che segue solo nodo a nodo, ma non il più breve dato che puoi passare attraverso alcuni poligoni e saltare nodi / spigoli.

Oh, e voglio anche sapere come suggerisci di memorizzare le informazioni relative ai poligoni. Per l'esempio del prototipo di waypoint che ho fatto, avevo solo ciascun nodo come oggetto e memorizzavo un elenco di tutti gli altri nodi che potevi raggiungere da quel nodo, immagino che non funzionerà con i poligoni? e come posso sapere se un poligono è aperto / attraversabile o se è un oggetto solido? Come posso memorizzare i nodi che compongono il poligono?

Infine, per la cronaca: voglio programmarlo da solo anche se ci sono già altre soluzioni disponibili e non ho intenzione di (ri) utilizzare questo codice in qualcosa di diverso da questo gioco, quindi non importa che sarà inevitabilmente di scarsa qualità.


Non sono sicuro, ma questi link potrebbero essere d'aiuto: gamedev.stackexchange.com/questions/1327/… gamedev.stackexchange.com/questions/8087/… c'era anche un'altra domanda sul percorso che non riesco a trovare in questo momento , che ha ottenuto una taglia e ha avuto un'ottima risposta.
Ali1S232,

Sì, nel secondo link puoi vedere la mia preoccupazione principale, l'algoritmo A * darebbe il percorso attorno al fondo come il più breve usando i punti medi del bordo ma il percorso attorno alla cima dell'ostacolo è in realtà il più breve. Voglio sapere come posso ottenere A * per darmi il percorso intorno alla cima che poi raddrizzerò (ad esempio con un algoritmo a imbuto) per ottenere il vero percorso più breve, dove come se mi desse quello intorno al fondo quindi anche se lo raddrizzo, sta ancora facendo una deviazione.
angrydust,

In realtà, ho appena letto l'articolo in gamedev.stackexchange.com/questions/8087/… e sembra funzionare trovando un percorso con A *, quindi calcolando il suo costo reale con un algoritmo a imbuto modificato e quindi trovando un altro percorso e calcolandolo vero costo di nuovo e vedere se è più corto dell'altro. Si ripete fino a quando non sa di aver trovato il percorso più breve. Questo in effetti risolve il mio problema, tuttavia, sembra che sarà piuttosto lento poiché stai ripetendo sia il raddrizzamento che la ricerca del percorso, il che sarebbe piuttosto costoso.
angrydust,

Archiviazione poligoni: archivia solo i poligoni visibili o associa un tag a ciascun poligono (ricorda che ogni poligono dovrà essere un elenco circolare di vertici); allo stesso modo con i nodi è possibile memorizzare l'ID del poligono da cui provengono, ma non dovrei dirti questo: è l'archiviazione dei dati elementare. Infine, perché ti preoccupi del vero percorso più breve? Il tuo gioco può rallentare il cane o puoi avere percorsi leggermente errati: scegline uno. Ottenere il percorso più breve vero RICHIEDE una ricerca completa in ampiezza (almeno su un grafico di nodo).
Jonathan Dickinson,

@JonathanDickinson So che non ho bisogno di un percorso che sarà accurato al 100% per l'ultimo pixel, e so che posso utilizzare A * per produrre percorsi che saranno al massimo p ammissibile. La cosa sta superando un ostacolo così chiaramente, come nella mia precedente domanda sullo stack overflow o in gamedev.stackexchange.com/questions/8087/… è semplicemente troppo. Non posso lasciare che la mia intelligenza artificiale passi in questo modo attorno a un ostacolo!
angrydust,

Risposte:


14

Vorrei consigliare che, anche se hai intenzione di scrivere tutto il tuo codice, di scaricare Rifusione e creare l'applicazione di esempio in quanto ha visualizzazioni che mostrano la navmesh generata e ti consente di testare il percorso con un semplice punto e fare clic interfaccia. Puoi imparare molto semplicemente giocando con quello.

Come hai già capito, ci sono due passaggi per produrre un percorso bello: il cercatore di percorsi A * e quindi la successiva post-elaborazione che include il raddrizzamento del percorso (l'eliminazione di eventuali curve non necessarie per evitare ostacoli) e possibilmente anche il aggiunta di curve ai punti di svolta.

Individuazione del percorso

Hai imparato la parte A * che è grandiosa. Hai anche fatto l'osservazione che A * non troverà sempre il percorso più dritto. È fondamentale capire che questo è perché A * è un algoritmo per trovare il percorso più breve attraverso un grafico (essendo un concetto matematico in cui i nodi sono senza dimensioni) quando lo si applica a una mesh, in qualche modo è necessario mappare i nodi su elementi mesh.

La cosa più ovvia da fare è spostarsi dal punto centrale del poligono al punto centrale e basare il costo su questa distanza, ma ciò presenta alcuni problemi. Uno è che non troverà sempre il percorso geometricamente più breve e il secondo è che se provi a seguire il percorso che hai calcolato lì noterai che una linea retta da un centro all'altro può attraversare un poligono che non è fa parte del percorso (e potrebbe non essere affatto navigabile). Non è un modo terribile di costare l'attraversamento del grafico mentre si esegue A *, ma chiaramente non è adeguato per qualsiasi scopo di attraversamento.

La prossima soluzione più semplice è eseguire A * da un bordo all'altro attraverso la mesh. Lo troverai più semplice da pensare se immagini che invece di un nodo per poligono, tu ne abbia uno per bordo per poligono. Quindi il tuo percorso va dal tuo punto di partenza appena all'interno del bordo più vicino, attraversa appena all'interno del bordo del poligono adiacente e quindi appena all'interno del bordo successivo nello stesso poligono e così via. Questo produce il percorso più breve più spesso e ha anche il vantaggio di essere percorribile se non si desidera eseguire un passaggio di raddrizzamento del percorso.

Raddrizzamento del percorso

L'algoritmo utilizzato in Detour (la libreria di navigazione che accompagna Recast) è piuttosto semplice. Dovresti osservare che raddrizzerà il percorso solo entro i limiti dei poligoni trovati durante la ricerca A *. Di conseguenza, se non trova il percorso più stretto attorno a un ostacolo, non otterrai neanche un percorso stretto dopo aver eseguito quell'algoritmo. In pratica, le reti navali prodotte dalla rifusione tendono ad avere un singolo poligono che puoi attraversare durante la navigazione di un punto di strozzatura (il punto più vicino tra due ostacoli) e quindi A * produrrà sempre un elenco di nodi vicini all'ostacolo quanto possibile. Se stai usando le tessere come navmesh, questo non sarà il caso e questo semplicissimo algoritmo inserirà curve spurie.

L'algoritmo di raddrizzamento del percorso della deviazione non è abbastanza O (n) in complessità perché quando determina che deve inserire una svolta, la inserisce nel punto in cui ha stretto l'ultima volta l'imbuto a sinistra (quando gira a sinistra e viceversa) e quindi inizia di nuovo a tracciare i nodi da quel punto.

Se vuoi raddrizzare il percorso al di fuori dei poligoni che fanno parte del percorso A *, le cose diventano molto più complesse. Dovrai implementare una routine ray-cast in grado di verificare se due punti nella tua navmesh possono vedersi (dovresti comunque farlo in modo da poter vedere se devi usare A *). Puoi farlo intersecando il segmento di linea formato dall'origine-> target con i bordi di connessione del poligono contenente l'origine, quindi testando i bordi di connessione del poligono che ti sposta all'interno e così via. Se intersechi un bordo non connesso (li chiamo bordi), allora hai colpito un ostacolo.

Puoi quindi eseguire questo test di ray-cast ogni volta che l'algoritmo di canalizzazione determina che è necessario inserire un turno per vedere se lo fa davvero, ma penso che dovrai continuare a eseguire quel test su ogni nodo fino a quando non inserisci un turno (a quale punto è possibile ripristinare al semplice algoritmo di canalizzazione). Sta diventando costoso, rendendo il raddrizzamento del percorso di circa O (n ^ 2).

Rappresenta la maglia

Puoi rappresentare la tua mesh come una matrice di classi poligonali. La classe poligonale potrebbe essere semplice come una matrice di vertici e una matrice di riferimenti al poligono adiacente per ciascun bordo, se presente. Ovviamente puoi probabilmente pensare a come conservarlo in modo più compatto. Poiché un vertice è generalmente condiviso da più poligoni, è normale avere una grande matrice di vertici e quindi ogni poligono memorizza gli indici in quella matrice. A seconda delle caratteristiche della tua navmesh potresti avere un numero medio di bordi di connessione pari solo al 50% o meno del numero di bordi. In tal caso, potresti voler memorizzare un collegamento a un altro poligono e all'indice del bordo anziché memorizzare un collegamento per ogni bordo. Inoltre, ti consiglio di memorizzare l'indice del poligono nell'array poligonale della navmesh anziché utilizzare un riferimento di classe.


Ho appena avuto una breve lettura di questo, ma capisco che non dovresti mai usare il quadrato della distanza (o non radice quadrata) per A *: theory.stanford.edu/~amitp/GameProgramming/…
angrydust

Non sono davvero preoccupato di come fare realmente il percorso che raddrizza atm, quello di cui sono preoccupato è quello che dici: "Dovresti osservare che raddrizzerà il percorso solo entro i limiti dei poligoni trovati durante la ricerca A * In quanto tale, se questo non trova il percorso più stretto attorno a un ostacolo, non otterrai neanche un percorso stretto dopo aver eseguito quell'algoritmo. "
angrydust,

Voglio avere una mesh nav in cui A * troverà sempre il percorso che una volta raddrizzato è il più breve, indipendentemente dal costo del viaggio attraverso vertici / punti medi. Mi rendo conto che questo può essere fatto con i grafici di visibilità, ma voglio usare una navmesh perché ha molti altri vantaggi e perché la complessità di un grafico di visibilità può crescere molto rapidamente: theory.stanford.edu/~amitp/GameProgramming/…
angrydust,

@theguywholikeslinux puoi usare la distanza euclidea sqrt(x*x + y*y)- ma non il più economico per nodo x*x + y*y.
Jonathan Dickinson,

@JonathanDickinson Lo so, quindi il mio punto.
angrydust,
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.