Algoritmo per il calcolo di un percorso di proiettile verso un obiettivo con max. 2 rimbalzi


21

Ci scusiamo per il titolo scadente ma non avevo un modo migliore per esprimerlo ...

Quindi c'è questo fantastico gioco per Nintendo (sì!) Su Wii chiamato WiiPlay . Ci sono 9 minigiochi al suo interno e il mio preferito si chiama Tanks! . Si tratta di distruggere i carri armati nemici della COM senza farsi distruggere. Ecco uno screenshot di un livello:

inserisci qui la descrizione dell'immagine

Un modo per distruggere i carri armati è sparando proiettili. C'è questo carro armato nemico verde lime che spara proiettili ad alta velocità che rimbalzano (contro le pareti e i blocchi) due volte. Puoi vedere come il carro armato del giocatore può essere immediatamente distrutto se rimane dove si trova ora, poiché quel carro armato di calce al centro può sparare un proiettile che segue il percorso verde che ho disegnato sull'immagine.

Come programmatore dilettante, mi sono chiesto come può il carro armato di calce determinare in quale direzione dovrebbe sparare per colpire il carro armato del giocatore.

Ci ho pensato da solo ma non ho trovato nessun algoritmo possibile. Spiegherò le mie conclusioni nel caso in cui ispirino qualcuno. Solo per semplicità durante la mia spiegazione, presumo che un muro sia qualsiasi superficie contro la quale un proiettile può rimbalzare . Un rettangolo isolato di blocchi forma così quattro pareti.

Ho concluso che i 2 punti in cui i rimbalzi dei proiettili si trovano sempre su un lato di un parallelogramma o diventano vertici opposti di un parallelogramma. Il carro armato nemico che spara e il carro armato del giocatore che mira non sono necessariamente gli altri 2 vertici, ma si trovano sicuramente sulle linee colinear a uno dei quattro lati del parallelogramma. Ecco un'illustrazione dei 4 possibili modi per formare un parallelogramma:

inserisci qui la descrizione dell'immagine

HOR-VER significa che il proiettile colpisce prima un muro orizzontale, quindi colpisce un muro verticale.

E poi sono bloccato. Ho pensato di spostarmi su una linea che collega il carro armato nemico e il carro armato del giocatore intorno alla mappa per vedere se forma un parallelogramma con due colpi con qualsiasi muro, ma questo non funziona sempre perché il carro armato nemico e il carro armato del giocatore non lo sono necessariamente coincidente con i vertici del parallelogramma.

Inoltre, non sono sicuro del flusso generale dell'algoritmo. L'algoritmo accetta una delle seguenti 2 strutture o forse mi sbaglio con entrambe?

  • Continua a capire i possibili percorsi e segna sempre uno dei migliori (può essere il più breve, il più oscuro, il più inevitabile o una valutazione combinata e ponderata basata su più criteri) e dimentica il resto. Quello rimasto dopo tutto il calcolo è il migliore da prendere.
  • Per prima cosa determinare tutti i muri prima raggiungibili con il proiettile (il proiettile non deve rimbalzare contro nessun altro muro per raggiungere ognuna di queste pareti), quindi determinare tutti gli intervalli raggiungibili su ciascuna di queste pareti (a volte è impossibile raggiungere un punto lontano su un muro senza rimbalzo se un altro muro si trova vicino a te), quindi di nuovo determinare tutti i muri raggiungibili con un rimbalzo e tutte le distanze raggiungibili su questi muri. Questi 4 processi possono essere eseguiti in modo simile al ray-tracing. Durante ogni processo, se il carro armato del giocatore viene colpito da un raggio, capire il percorso del proiettile secondo quel raggio.

Secondo me, questo algoritmo è difficile da capire perché:

  • un proiettile può essere sparato in qualsiasi direzione; e
  • ci sono infiniti punti su ogni muro, come in matematica, dove ci sono infiniti punti su una linea.

Ma la gente Nintendo ce l'ha fatta comunque, quindi ... qualcuno con un'idea?


Solo per verificare, stai chiedendo come potrebbe essere fatto, non come Nintendo ha scelto di farlo, giusto?
Ixrec,

@lxrec hai ragione, sono solo interessato a un modo possibile per farlo, non nel modo in cui l'hanno fatto .
ciao tutto il

Il gioco non ha bisogno di trovare una soluzione. Quando premi il pulsante per sparare, il gioco conosce già la tua posizione e direzione che stai affrontando, quindi usa solo quelle informazioni. Traccerà la traiettoria e se trova il carro nemico nel percorso lo colpirai altrimenti no.
Mandrill,

2
Mentre ci sono "infinitamente" molti angoli, puoi facilmente ridurli a poche classi di equivalenza. Sight and Light di Nicky Case è una bella demo di rendering delle ombre tra poligoni - che è esattamente il tuo problema, tranne per il fatto che stai usando percorsi di proiettile piuttosto che raggi di luce, e che i tuoi raggi potrebbero essere riflessi due volte. Nota che il riflesso non ha importanza per l'IA: il riflesso si estende semplicemente alla linea di vista, sebbene ciò significhi che lo stesso oggetto può essere visibile da più angolazioni.
Amon,

@Mandrill Temo che tu non abbia capito bene la mia domanda. Stavo chiedendo come il carro armato nemico può escogitare un percorso di proiettile che colpisce il carro armato del giocatore.
ciao tutto il

Risposte:


9

Dato un orientamento diretto, il problema è ovviamente banale. Tuttavia, abbiamo a che fare con la riflessione. Scoprire correttamente quali parti della scena possono essere viste è una sfida quando si implementa la riflessione come parte di un ray tracciante, dal momento che questo potrebbe perdere alcune aperture. Anche una "ricerca binaria" tra due angoli promettenti non è praticabile: a causa dei riflessi, lo spazio effettivamente visibile non è continuo, quindi l'euristico "se è alla destra di A e alla sinistra di B, ci deve essere un obiettivo la soluzione tra A e B " non è consentita e mancherà soluzioni" creative ". Vorrei invece raccomandare di implementare la riflessione rieseguendo il tracciante da una posizione virtuale, la posizione in cui il nostro carro armato sembra essere quando viene visto allo specchio:

target |obstacle
   X   |
    \  |  X real position
     \   /
      \ /
   ----------- mirror surface
        \
         \
          X virtual position

Il vantaggio è che il raggio speculare è ora una linea retta proveniente dalla posizione virtuale. Ho cercato di illustrare la tecnica nel seguente schizzo:

sparando dietro gli angoli

X segna la posizione di fuoco, (X) il bersaglio. Le aree colorate sono visibili.

  1. Linea di mira diretta: l'obiettivo non è visibile. Tuttavia, possiamo colpire le superfici (1) e (2).

  2. Una riflessione. Ci sono due posizioni di tiro virtuali all'interno degli ostacoli. La posizione inferiore ha LOS diretto verso il bersaglio, quindi abbiamo la nostra prima soluzione di fuoco: il percorso del proiettile è la parte del raggio tra il bersaglio e la superficie dello specchio inferiore e tra il punto di collisione raggio-specchio e la posizione di fuoco reale.

  3. Due riflessioni: la posizione virtuale superiore della prima riflessione può vedere parte dell'ostacolo inferiore attraverso la sua superficie a specchio. Poiché sono consentite due riflessioni, possiamo rispecchiare questa posizione nell'ostacolo inferiore. Le posizioni sono contrassegnate come (I) la posizione reale, (II) la posizione virtuale dalla prima riflessione e (III) la posizione virtuale dalla seconda riflessione.

    Da (III), abbiamo LOS diretto al bersaglio (X), quindi abbiamo trovato un'altra soluzione di fuoco. Il percorso del proiettile è lungo la linea X – III fino al secondo punto di collisione dello specchio, quindi lungo la linea III – II tra i punti di collisione dello specchio e infine lungo la linea II – I dal primo punto di collisione dello specchio alla posizione reale I.

    In realtà, anche la posizione virtuale inferiore della prima riflessione potrebbe riflettersi nell'ostacolo superiore, ma ciò non porterà a soluzioni dirette.

Una volta che puoi capire quali parti degli ostacoli sono visibili (e possono quindi essere utilizzate per riflettere il proiettile), l'implementazione del mirroring tramite una ricerca approfondita sembrerebbe semplice. Per trovare superfici a specchio adatte, si potrebbero usare le tecniche descritte in Sight & Light di Nicky Case : piuttosto che provare 360 ​​vettori - che potrebbero mancare aperture, ed è anche dispendioso - lanciamo raggi solo ai bordi degli ostacoli.


Non capisco come funzionano "il lancio di raggi solo ai bordi degli ostacoli". Intendi iniziare a lanciare raggi verso la fine delle pareti e gradualmente verso l'interno fino a trovare una soluzione? In tal caso, capisco che con questa regola la soluzione può essere trovata più rapidamente.
ciao tutto il

Dopo alcune considerazioni, penso che questa sia la risposta migliore perché, ovviamente, con la risposta matematica che ho contrassegnato come migliore in precedenza, non è in grado di gestire direttamente soluzioni con un rimbalzo e senza rimbalzo.
ciao tutto l'

È brillante! Qualche consiglio su come creare una rappresentazione speculare del tuo livello senza essere troppo esigente nel tuo gioco?
retrovius

7

Basta estendere l'idea di Karl Bielefeldt per un riflesso di 2 pareti:inserisci qui la descrizione dell'immagine

Vengono indicati A e B (i carri armati). Devi prima elencare tutti i muri che A può vedere e un elenco di tutti i muri che B può vedere. Quindi si creano coppie in cui il primo muro è nell'elenco dei pugni e il secondo muro è diverso dal primo muro ed è nel secondo elenco. Devi fare questo test per tutte le possibili coppie di muri (a meno che non trovi un modo per eliminare i candidati). Quando trovi R e S per una data coppia di muri, controlli

1) se A ha visione diretta di R

2) se R appartiene al muro1 (il muro è solo un segmento, non l'intera linea)

3) se R ha accesso diretto a S

4) se S appartiene a wall2 (il muro è solo un segmento, non l'intera linea)

5) se S ha accesso diretto a B.

Per trovare R e S : Poiché conosci wall1 puoi determinare l'equazione della linea tangente al wall1, poiché R appartiene alla linea tangente al wall 1, hai una relazione tra le 2 coordinate di R (che termina con un grado di libertà per R) Analogamente a S (hai una relazione tra le coordinate S poiché questo punto appartiene alla linea tanget a wall2). Quindi ora hai 2 gradi di libertà e devi avere 2 equazioni indipendenti aggiuntive per determinare una soluzione. Un'equazione è:

(AA')/(RA')=(SS')/(RS')

l'altra equazione è:

(BB')/(SB')=(RR')/(SR')

si noti che nelle equazioni precedenti A, A ', B, B' sono note o possono essere calcolate direttamente. R 'e S' sono funzione delle coordinate di R e S e delle equazioni del muro. Non ho finito la matematica, quindi non so come appariranno le equazioni.


Questo è un grande approccio matematico. Ma l'algoritmo richiede molto tempo di calcolo per risolvere le equazioni simultanee, immagino? Ci sono molte radici quadrate ed esponenziali coinvolti con le distanze.
ciao tutto il

3

Puoi trarre vantaggio dal fatto che l'angolo che lascia il rimbalzo deve essere lo stesso dell'angolo che lo immette. Per una data parete orizzontale con coordinata y ce due serbatoi fissi con coordinate (a,b)e (d,e), esiste un solo angolo che soddisfa l'equazione di seguito.

diagramma dell'equazione

Risolvi semplicemente per xottenere la distanza lungo il muro a cui devi mirare. Due pareti funzionano allo stesso modo. Hai solo due equazioni e due incognite.


1

Hai diagrammi accurati che mostrano come dirigere i raggi, quindi lascerò i dettagli su come determinare una coppia di superfici riflettenti.

Chiamiamo la superficie che deve essere colpito prima superficie A , e la seconda, B .

Tenta di colpire i bordi (visibili) di B sparando A . In altre parole, determinare i punti in cui si vedrebbero i riflessi delle estremità di B se si guardasse A con finitura a specchio . Questo deve essere facile da fare, hai solo un punto di riflessione da gestire.

Ora si sa due raggi che colpiscono i bordi (visibili) di B . Chiamiamoli raggi di bordo Calcola i loro riflessi da B; devono andare da qualche parte oltre il tuo obiettivo. Puoi determinare se il bersaglio si trova tra di loro, cioè a sinistra di un raggio ma a destra dell'altro, o viceversa. Questo è banale da fare usando l' equazione generale della linea retta .

Se il bersaglio non è tra i raggi del bordo, ovviamente non puoi colpirlo con nessun raggio intermedio; scegli un'altra coppia di superfici.

Se il bersaglio si trova tra i raggi, cerca il raggio di colpire intermedio usando la ricerca binaria. Hai due angoli di fuoco corrispondenti ai raggi del bordo, il tuo angolo di colpire si trova tra di loro. A condizione che il diametro angolare del bersaglio, visto dal punto di fuoco, non sia eccessivamente piccolo, avrai bisogno di poche iterazioni finché non trovi la direzione di un raggio colpente.

Ecco una foto:

raggi

Qui i due raggi del bordo sono mostrati in rosso e blu. Apparentemente puoi trovare un raggio emesso con un angolo più piccolo di quello rosso ma maggiore di quello rosso in modo che quel raggio colpirà il bersaglio verde.


No, non necessariamente! Pensa al tuo diagramma se ci fosse un ulteriore ostacolo in qualsiasi punto tra i percorsi dei proiettili rosso e blu. Se spari un proiettile ad angolo retto tra gli angoli rosso e blu, potresti ottenere un colpo più vicino al carro armato del giocatore, ma potresti anche perdere completamente perché alcuni proiettili potrebbero rimbalzare su qualche ostacolo casuale che si trova in mezzo. Si prega di consultare la risposta di @amon dove discute di questa possibilità.
ciao tutto il

Upvoted @ amon's answer; Mi piace l'idea del mirroring lineare. Suppongo anche che l'algoritmo dovrebbe verificare che il percorso di colpire sia effettivamente percorribile dopo averlo trovato in questo modo semplificato. Ancora più interessante è una possibilità in cui il bersaglio è solo parzialmente occluso (forse anche diviso in due regioni visibili). Il metodo di Amon è più suscettibile alla sua gestione.
9000,

-3

Prima di tutto, ricordi durante le lezioni di fisica quando hai parlato della rifrazione della luce? Bene, il tuo problema può essere risolto usando questi principi. L'angolo di incidenza è uguale all'angolo di riflessione. quindi il carro armato nemico deve percorrere ogni angolo possibile per il primo rimbalzo in modo che il secondo rimbalzo possa colpire il giocatore. Continua anche con l'idea del ray tracing. Ora, questo diventa complicato quando il giocatore si sta muovendo, ma dovrebbe essere una buona idea per iniziare su un algoritmo


1
Capisco i principi della riflessione. Puoi vedere la mia risposta al commento di @amon. Hai ragione sul fatto che il movimento del giocatore deve essere preso in considerazione, ma penso che possa essere lasciato come un criterio per la scelta di uno ottimale tra molteplici percorsi possibili in base alla valutazione. Tuttavia, questo può essere ignorato perché è correlato alla distanza del percorso del proiettile, ovvero , più lungo è il percorso, più il giocatore può muoversi prima che il proiettile raggiunga la destinazione.
ciao tutto il
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.