Come si determinerebbe la posizione di un partecipante in un gioco di corse?


9

Ora, per la cronaca, al momento non sto implementando alcun gioco di corse, ma questo problema mi è appena venuto in mente e ora sono curioso.

Quindi, come si potrebbe scoprire quale partecipante a una gara è attualmente la prima? Non può essere qualcosa di banale come solo l'ordinamento per distanza dal traguardo perché sarebbe altamente impreciso sulla maggior parte dei percorsi. Ho pensato di fare qualcosa come separare il percorso in segmenti dritti, ognuno dei quali ha un vettore di direzione. Il gioco verificherebbe quindi quando qualcuno supera qualcun altro proiettando le loro posizioni su quel vettore e controllando quale è avanti. Se la posizione è cambiata, il gioco le incrementerebbe / decrementerà in modo appropriato. Ma sembra un po 'troppo complicato.

Qualcuno sa di metodi consolidati o ha esperienza nella realizzazione di alcuni?

Risposte:


12

Shawn Hargreaves descrive come la MotoGP abbia utilizzato uno speciale sistema di posizione relativo alla pista . Ignorando la posizione verticale y, le coordinate cartesiane x / z vengono tradotte in un sistema relativo alla traccia. Ciò ha comportato numerosi vantaggi per i calcoli che coinvolgono le posizioni relative dei partecipanti a un gioco di corse (ad esempio per l'IA):

Una semplificazione comune è quella di comprimere il 3D in 2D. Anche se il rendering e la fisica possono essere veramente 3D, la logica decisionale non deve necessariamente trattare tutti e tre gli assi allo stesso modo. Le piste della MotoGP hanno poche colline, quindi la nostra IA è stata in grado di ignorare la componente y.

Successivamente, siamo passati dalle coordinate cartesiane x / z a un sistema relativo alla traccia. Le posizioni erano rappresentate da una coppia di valori:

int distance = quanto intorno alla traccia, memorizzato in formato punto fisso 16.16

  • 0 = linea di partenza
  • 0x8000 = a metà strada
  • 0x10000 = riavviato all'inizio
  • 0x1C000 = tre quarti del percorso nel secondo giro

float cross = quanto lateralmente attraverso la traccia 0 = sulla linea centrale

  • -1 = bordo sinistro della superficie di corsa
  • 1 = bordo destro della superficie di corsa

Per convertire tra questo e le coordinate cartesiane utilizzate dal nostro codice fisico e di rendering, abbiamo memorizzato un elenco di segmenti che definiscono la forma della superficie di corsa: struct TrackSegment {Vector CenterPoint; float DistanceToLeftEdge; float DistanceToRightEdge; }

Abbiamo creato diverse centinaia di queste strutture, distribuite uniformemente intorno alla traccia, tessellando le curve di Bezier da cui le tracce sono state originariamente create. Questo ci ha fornito informazioni sufficienti per scrivere le necessarie funzioni di conversione delle coordinate.

Con le coordinate relative alla traccia, molti calcoli utili diventano banalmente semplici:

if (abs(cross) > 1)
    // You are off the track and should steer back toward the center line


if (this.distance > other.distance)
    // You are ahead of the other player (even though you may be
    // physically behind in 3D space if you have lapped them)


short difference = (short)(this.distance - other.distance);

if (abs(difference) < threshold)
    // These two bikes are physically close together,
    // so we should run obstacle avoidance checks

A causa del formato dei dati a virgola fissa, lanciare il contatore della distanza da 32 a 16 bit era un modo semplice per scartare il numero del giro, in modo da poter scegliere quali calcoli dovevano preoccuparsi se due bici si trovavano su giri diversi, invece di voler sapere se erano vicini nello spazio fisico. Grazie alla magia del complimento per due, trattare la differenza come un segno a 16 bit fornisce la distanza più breve indipendentemente da quale bici sia davanti (ricorda che in un sistema aritmetico modulo come una pista ciclabile ci sono due possibili distanze, come puoi misurare in in entrambe le direzioni intorno alla pista). Funziona anche quando le due bici si trovano ai lati opposti della linea di partenza, una situazione che richiederebbe una logica di casi speciali soggetta a errori nella maggior parte degli altri sistemi di coordinate.

Appiattire e raddrizzare questa area di gioco virtuale ha reso facile ragionare su cose come "Sono sulla linea di corsa?" o "Sto arrivando velocemente dietro quest'altra bici: ho più spazio per passarle a sinistra oa destra?" che sarebbe stato complicato da implementare in uno spazio mondiale 3D. Una volta deciso di passare a sinistra, convertiremmo le coordinate risultanti relative alla traccia nello spazio mondiale, a quel punto viene presa in considerazione la curvatura della traccia, mostrando come dovremmo guidare per raggiungere il nostro obiettivo prescelto.


Molto bella! Molte grazie. Grazie anche per l'aggiunta di tag appropriati. Non sono stato in grado di farlo a causa della mancanza di reputazione. Saluti.
Marc Müller,

3

Immagino che userei il fatto che la strada è generalmente costruita usando spline, quindi ogni bordo della strada ha una posizione spline corrispondente, e usando ciò potresti determinare (approssimativamente o granulosamente se suddividi ulteriormente) quale sia la corrente posizione della spline di ogni auto è, e quindi chi è in testa. Quindi, più o meno come suggerisci, basta usare la spline.


3

Hai più o meno risposto alla tua domanda, credo. Dividi la traccia in segmenti, traccia in quale segmento si trova ciascuna auto e proietta le auto su una linea attraverso il centro del segmento appropriato (matematicamente è un semplice punto-prodotto, quindi non è affatto complicato). Molto semplice dare ad ogni auto una "distanza" che puoi ordinare per posizione.

I segmenti ti offrono un ulteriore vantaggio: puoi assicurarti che le macchine non tagliano le curve (o in generale non facciano scorciatoie), vanno indietro o altri trucchi.

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.