2011-01-14 13 views
6

Sto tentando di progettare un algoritmo di rilevamento delle collisioni per un client Minecraft personalizzato che sto creando. Fondamentalmente, il mondo intero è composto da cubi e il giocatore (o la telecamera) deve essere in grado di stare in piedi e muoversi contro questi cubi. Il risultato che voglio è illustrato in questa immagine: imageRilevamento di collisioni scorrendo contro un piano in XNA

La linea verde è il vettore di movimento del giocatore. Quando il giocatore sta sfiorando il piano di uno dei cubi, voglio che il vettore diventi uno perpendicolare al piano. Il vettore dovrebbe, tuttavia, mantenere tutta la sua velocità nella direzione del piano, ma perdere tutta la velocità verso il piano.

Spero di aver chiarito la mia domanda. Qual è il modo migliore e più efficace per implementare un sistema di rilevamento collisioni come questo? Inoltre, un sistema come questo consente una semplice componente di gravità?

MODIFICA: dimenticato di menzionare, i cubi sono memorizzati in una matrice tridimensionale, [x, y, z].

+0

amo questa domanda. Ti suggerirei di pubblicare anche su gamedev.stackexchange.com. Immagino che questo sia un problema comune nello sviluppo del gioco. –

+0

@BigDave - Oh, non sapevo che esistesse un sito specifico per lo sviluppo del gioco. Lo Stack Exchange sta davvero crescendo. – Bevin

risposta

1

Un approccio semplice all'implementazione sarebbe quello di rilevare la collisione della palla e dell'aereo. Calcola la profondità di penetrazione, in questo modo la palla è effettivamente passata oltre l'aereo e spinge indietro la palla nella direzione normale del piano.

Questo avrà l'effetto di mettere la palla sulla superficie dell'aereo. Se lo fai per ogni fotogramma, la palla scivolerà efficacemente lungo il piano, assumendo ovviamente che il vettore di velocità della palla non sia parallelo alla normale del piano.

Il campo del rilevamento delle collisioni è grande e complesso e, a seconda del gioco, è necessario determinare ciò che è sufficiente per le proprie esigenze in termini di livello di realismo richiesto e requisiti di prestazioni. Dovresti sempre cercare la soluzione più semplice che dia un feedback abbastanza realistico, a seconda del gioco che spesso non deve essere perfetto.

Fondamentalmente si dovrebbe rompere il rilevamento di collisione in 2 fasi tipicamente note come fase ampia e fase stretta.

La fase di ampia potrebbe essere semplice come effettuare un controllo rettangolo di selezione rapida per determinare potenziali collisioni e quindi inviare quelli potenziale collisione al rilevamento di fase di collisione stretta per fare i controlli più dettagliati in cui si determina se ci fosse davvero una collisione e la profondità di collisione. Se si dispone di molti oggetti, la fase ampia potrebbe utilizzare una sorta di indicizzazione quadrifoglio per selezionare solo i blocchi nelle vicinanze dell'oggetto per eseguire il rilevamento delle collisioni contro.

+0

@Chris Taylor - Sì, ho pensato che potesse essere qualcosa di così semplice. Come pensi che dovrei andare a calcolarlo? Devo solo scorrere un sottoinsieme di cubi e controllare se il giocatore si sta intersecando con uno di loro? – Bevin

+0

@Bevin, la mia risposta alla tua domanda extra è durata un po ', quindi ho semplicemente aggiornato la risposta con qualche informazione in più. Spero che questo ti aiuti. –

+0

@Chris Taylor - Beh, conosco le dimensioni del giocatore, quindi potrei semplicemente scorrere i cubetti che sono, ad esempio, al massimo a 4 isolati di distanza. Questo dovrebbe dare abbastanza spazio per il rilevamento. Come posso scoprire fino a che punto il giocatore si è intersecato e quanto spingerlo fuori dal blocco? – Bevin

0

In un mondo di cubi allineati all'Asse, questo è veramente facile. È facile pensare che tu abbia bisogno di qualcosa di elaborato, ma in realtà è davvero semplice. Questo deriva dall'esperienza dopo aver scritto il mio clone di minecraft.

Ecco come:

position.X += velocity.X; 
if(colliding()) 
    position.X -= velocity.X; 

position.Y += velocity.Y; 
if(colliding()) 
    position.Y -= velocity.Y; 

position.Z += velocity.Z; 
if(colliding()) 
    position.Z -= velocity.Z; 

Ecco il codice per scoprire se si sta collisione o no:

bool colliding() 
{ 
    int minX = Position.X - size.X/2; 
    int minY = Position.Y - size.Y/2; 
    int minZ = Position.Z - size.Z/2; 

    int maxX = Position.X + size.X/2; 
    int maxY = Position.Y + size.Y/2; 
    int maxZ = Position.Z + size.Z/2; 

    for (int x = minX; x <= maxX; x++) 
    for (int y = minY; y <= maxY; y++) 
     for (int z = minZ; z <= maxZ; z++) 
     { 
     if(blockType[x, y, z] != 0) 
      return true; 
     } 

    return false; 
} 
+0

Questo non funzionerà se il lettore non è allineato. Cosa succede se il giocatore interseca solo leggermente uno degli aerei? Quindi verrà spinto oltre il necessario. – Bevin

+0

Il giocatore può essere trattato come una scatola allineata sull'asse non di rotazione a scopo di collisione. Funziona bene. So cosa intendi, ma non è notabile dal giocatore. Incoraggerei l'OP a fare un tentativo. – Hannesh

Problemi correlati