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.