Comment déterminer la position d'un participant à un jeu de course?

9

Maintenant, pour mémoire, je n'implémente actuellement aucun jeu de course, mais ce problème vient de me venir à l'esprit et maintenant je suis curieux.

Alors, comment procéder pour savoir quel participant à une course est actuellement le premier? Cela ne peut pas être quelque chose de trivial comme simplement trier par distance jusqu'à la ligne d'arrivée car cela serait très imprécis sur la plupart des parcours. J'ai pensé à faire quelque chose comme séparer l'itinéraire en segments droits, chacun ayant un vecteur de direction. Le jeu vérifierait alors quand quelqu'un devance quelqu'un d'autre en projetant sa position sur ce vecteur et en vérifiant lequel est devant. Si la position a changé, le jeu les incrémenterait / décrémenterait de manière appropriée. Mais cela semble un peu trop compliqué.

Quelqu'un connaît-il des méthodes établies ou a-t-il une expérience dans leur mise en œuvre?

Marc Müller
la source

Réponses:

12

Shawn Hargreaves décrit comment le MotoGP a utilisé un système spécial de position relative à la piste . En ignorant la position verticale y, les coordonnées cartésiennes x / z sont converties en un système relatif à la piste. Cela avait de nombreux avantages pour les calculs impliquant les positions relatives des participants à un jeu de course (par exemple pour l'IA):

Une simplification courante consiste à réduire la 3D en 2D. Même si le rendu et la physique peuvent être vraiment en 3D, la logique de prise de décision n'a pas besoin de traiter les trois axes de manière égale. Les pistes MotoGP ont peu de collines, notre IA a donc pu ignorer la composante y.

Ensuite, nous sommes passés des coordonnées cartésiennes x / z à un système relatif à la piste. Les positions étaient représentées par une paire de valeurs:

int distance = la distance autour de la piste, stockée au format 16.16 point fixe

  • 0 = ligne de départ
  • 0x8000 = à mi-chemin
  • 0x10000 = rebouclé au début
  • 0x1C000 = trois quarts du chemin à travers le deuxième tour

float cross = la distance latérale sur la piste 0 = sur la ligne médiane

  • -1 = bord gauche de la surface de course
  • 1 = bord droit de la surface de course

Pour convertir entre cela et les coordonnées cartésiennes utilisées par notre physique et notre code de rendu, nous avons stocké une liste de segments définissant la forme de la surface de course: struct TrackSegment {Vector CenterPoint; float DistanceToLeftEdge; float DistanceToRightEdge; }

Nous avons créé plusieurs centaines de ces structures, régulièrement espacées autour de la piste, en tessellant les courbes de Bézier à partir desquelles les pistes ont été créées à l'origine. Cela nous a donné suffisamment d'informations pour écrire les fonctions de conversion de coordonnées nécessaires.

Avec les coordonnées relatives à la piste, de nombreux calculs utiles deviennent trivialement simples:

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

En raison du format de données à virgule fixe, la conversion du compteur de distance de 32 à 16 bits était un moyen facile de supprimer le numéro du tour, afin que nous puissions choisir et choisir les calculs qui importaient si deux vélos se trouvaient sur des tours différents, par opposition à vouloir savoir s'ils étaient proches dans l'espace physique. Grâce à la magie du compliment de deux, le fait de traiter la différence comme signée en 16 bits donne la distance la plus courte quel que soit le vélo devant (rappelez-vous que dans un système modulo arithmétique tel qu'un circuit en boucle, il y a deux distances possibles, comme vous pouvez le mesurer dans dans les deux sens autour de la piste). Cela fonctionne même lorsque les deux vélos sont sur des côtés opposés de la ligne de départ, une situation qui nécessiterait une logique de cas particulier sujette aux erreurs dans la plupart des autres systèmes de coordonnées.

L'aplatissement et le redressement de cette zone de jeu virtuelle ont permis de raisonner facilement sur des choses comme "suis-je sur la ligne de course?" ou "Je monte vite derrière cet autre vélo: ai-je plus de place pour les dépasser à gauche ou à droite?" ce qui aurait été difficile à mettre en œuvre dans un espace mondial en 3D. Une fois que nous avons décidé de passer à gauche, nous reconvertirions les coordonnées relatives à la piste résultantes dans l'espace mondial, à quel point la courbure de la piste serait prise en compte, montrant comment nous devrions nous diriger pour atteindre l'objectif choisi.

Leftium
la source
Très agréable! Merci beaucoup. Merci également d'avoir ajouté les balises appropriées. Je n'ai pas pu le faire par manque de réputation. À votre santé.
Marc Müller
3

Je suppose que j'utiliserais le fait que la route est généralement construite en utilisant des splines, donc chaque bord de la route a une position de spline correspondante, et en utilisant cela, vous pouvez déterminer (approximativement, ou à grain fin si vous subdivisez plus loin) ce que le courant position spline de chaque voiture est, et donc qui est en tête. Donc, plus ou moins comme vous le suggérez, en utilisant simplement la spline.

Kaj
la source
3

Vous avez plus ou moins répondu à votre propre question, je pense. Divisez la piste en segments, suivez le segment dans lequel chaque voiture se trouve et projetez les voitures sur une ligne passant par le milieu du segment approprié (mathématiquement, c'est un simple produit scalaire, donc pas compliqué du tout). Très simple pour donner à chaque voiture une "distance" que vous pouvez trier pour la position.

Les segments vous offrent un avantage supplémentaire - vous pouvez vous assurer que les voitures ne prennent pas les virages (ou ne prennent généralement pas de raccourcis), ne reculent pas ou ne trichent pas.

JasonD
la source