2010-10-10 9 views
6

Sto lavorando a un gioco basato su tessere 3D e sto utilizzando il rilevamento delle collisioni AABB. Per ogni cubo che il giocatore si sta intersecando, trovo l'asse lungo il quale il giocatore sta intersecando il cubo, e spingo il giocatore fuori dal cubo lungo quell'asse.Sliding AABB scorrevole - rimanere bloccato sui bordi

A seconda dell'ordine in cui i cubi sono registrati, ciò può causare problemi durante lo scorrimento lungo il bordo di più cubi. Ho creato un diagramma che dovrebbe spiegare il problema:

http://imgur.com/mmK0W.png

  • Freccia # 1 è il tentativo di movimento del giocatore. Le altre frecce sono la risposta di collisione.
  • Nel diagramma di sinistra, la collisione viene prima verificata rispetto al cubo destro, facendo in modo che il giocatore venga spinto a sinistra, e quindi verso l'alto. (errato)
  • Nel diagramma di destra, la collisione viene prima verificata contro il cubo di sinistra, facendo in modo che il giocatore venga spinto verso l'alto, a quel punto il giocatore non interseca più l'altro cubo. (buona)

Tutte le idee su ciò che il modo più efficace per risolvere questo potrebbe essere? O qualche modo migliore per gestire la risposta alla collisione?

Grazie.

+3

controllare Forse tutte le collisioni e prendere nota del tempo (o la distanza) della collisione. Applicare solo la collisione che si verifica al più presto. Opzionalmente, continua il processo per il resto del time-step. –

+0

Quindi, se ho ordinato tutti i cubi che il giocatore stava intersecando per distanza dal giocatore, e quindi considerato uno alla volta, potrebbe funzionare. Sto pensando che sarebbe meglio evitare di dover ordinare le cose ogni fotogramma, ma non sono sicuro che sarebbe molto importante dal momento che il giocatore potrebbe essere in collisione solo con un massimo di? 7? blocchi alla volta. Pensi che ci sia qualcosa di cui preoccuparsi? – Jeff

risposta

4

Un'implementazione discreta costringe a inserire alcuni calcoli matematici continui nel sistema, solo quando richiesto (cubi/direzioni si sovrappongono).

Per ogni cubo c1, c2 ... ci con cui l'utente cubo (uc) interseca al momento del controllo, si vuole scoprire quale cubo è stato "toccato" prima - ce n'è solo uno, come nella vita reale. Si consideri la direzione d di uc, e, prendendo la quantità di uc in CI (sovrapposizione) trovare la posizione di cu nel momento in cui "toccato" ci.

determinare quale cubo è stato "toccato" prima cj (quello che ha richiesto più di rollback sull'asse d - la prima nel tempo) e utilizzare solo questo per calcolare la reazione di collisione.

Non solo si raggiunge la precisione. ma sarà d'aiuto se tutti i cubi si muovono, hanno velocità diverse ecc ...

+0

+1. Ho fatto una cosa del genere una volta, anche se è difficile implementare ed eseguire il debug. È possibile incontrare dei problemi usando questo approccio quando il movimento degli oggetti da un fotogramma all'altro non è lungo una linea lineare, ma per il resto funziona davvero bene. Dovrai ricordare la posizione precedente (e forse la velocità precedente) di ciascun oggetto che può muoversi in modo da poter calcolare la posizione e la velocità degli oggetti in un dato momento tra due fotogrammi. – Cameron

+0

Ho qualche problema a capire quello che stai dicendo, ma penso che questa risposta avrebbe anche un problema se il giocatore stesse cercando di entrare in un angolo di una stanza. Credo che sarebbe necessario prendere in considerazione più di un blocco. Potrei forse ordinare tutti i blocchi con cui il giocatore è in collisione, ma non sono sicuro se sarebbe meglio evitare di dover ordinare le cose. – Jeff

+0

Il muro della stanza deve essere trattato allo stesso modo degli altri cubi - questo è un caso particolare (più semplice): si controlla se il cubo è fuori dai limiti e, usando lo stesso algoritmo, si determina quanto del cubo è fuori, quindi controlli le collisioni con altri cubi. Di nuovo, il primo "toccato" (un altro cubo o il muro) deve essere trattato con la reazione di collisione. Il muro è solo un particolare oggetto non mobile e più grande con il quale il cubo può entrare in collisione. –

0

Dal diagramma, sembra che si desideri la minima mossa che minimizzi la sovrapposizione tra il giocatore e i cubi. Ogni cubo con sovrapposizione tenterà di "spingere" il giocatore in due direzioni ortogonali. Puoi fare qualcosa come scegliere la spinta minima delle massime spinte in ogni direzione?

+0

Penso che causerebbe problemi se il giocatore stava camminando in un angolo. In tal caso, ho bisogno di spingere il giocatore indietro lungo 2 assi. – Jeff

+0

OK; pensando in 2D, la spinta deve avere una componente verticale e orizzontale. Ogni cubo sovrapposto può impartire una spinta in due direzioni da {N, S, E, W}. Se ci sono più cubi sovrapposti, devi considerare le massime spinte nelle direzioni {N, S} e {E, W} (qualsiasi cosa di meno lascerà sovrapposizioni, ma potrebbe essere possibile ignorare, ad esempio, una spinta NS perché una spinta EW farà il lavoro). Ci sono al massimo otto possibilità. Puoi provare tutti e otto in ordine di grandezza e scegliere il primo che cancella il giocatore dai cubi? – Rafe

+0

Sfortunatamente, ci sarebbero ancora più serie possibili in 3 dimensioni. Probabilmente sarebbe più efficiente ordinare i blocchi in base alla distanza come suggeriva Tom. – Jeff

0

Si potrebbe implementare un tipo di fase ampia ibrida quando i due (o più) cubi stazionari di fila possono essere combinati in un rettangolo più grande. Prova prima contro il rettangolo più grande. Ti darà i risultati del tuo segno di spunta verde e sarà più veloce di controllare comunque ogni cubo. Quindi, dopo, solo se necessario, controlla i singoli cubi.

+0

Sto provando a pensare a come applicarlo a 3 dimensioni. Se avessi una forma come una "L" in piedi, potrei combinare 2 blocchi orizzontalmente o verticalmente. Ma penso che l'ordine in cui dovrei applicare la risposta dipenda dalla posizione del giocatore o dalla direzione del movimento. – Jeff

0

Una collisione può spingere un oggetto solo su 1 asse. Per determinare l'asse da premere:

else -- not this 
elseif -- change to this 

if w > h then 
    push x 
elseif h > w then 
    push y 
end 

Questo funziona se le piastrelle sono allineate.

Utilizzare i cerchi per evitare il bastone su piastrelle non allineati

Problemi correlati