Ce n'est pas si difficile de créer un assez bon mouvement de voiture (mais ce post sera assez long). Vous devrez "simuler" quelques forces de base pour rendre la voiture physiquement plausible.
(Tous les exemples de code sont des pseudocodes.)
Accélération
Tout d'abord, vous aurez évidemment besoin d'une accélération. Quelque chose d'aussi simple que la ligne suivante ferait:
acceleration_vector = forward_vector * acceleration_input * acceleration_factor
forward_vector
- Un vecteur pointant dans la même direction que la voiture.
acceleration_input
- L'entrée doit être dans l'intervalle [-1, 1].
acceleration_factor
- La valeur de l'accélération (pixels / seconde ^ 2, ou quelles que soient vos unités).
Pilotage
La direction est également assez simple. En principe, vous allez faire pivoter le vecteur avant de la voiture pour le faire pointer dans une autre direction.
steer_angle = steer_input * steer_factor
new_forward_vector = rotate_around_axis(forward_vector, up_vector, steer_angle)
Vous pourriez cependant rencontrer une complication ici. Si votre saisie se fait via un clavier, sa valeur sera soit -1 soit 1 ce qui signifie que votre voiture tournerait instantanément. Vous pouvez résoudre ce problème en utilisant une interpolation linéaire très simple (lerping):
amount = time_since_last_frame * steer_lerp_factor
forward_vector = lerp(forward_vector, new_forward_vector, amount)
Le montant doit dépendre du temps de sorte que votre mouvement ne dépende pas de votre fréquence d'images. Le montant doit être compris entre [0, 1] et plus il est petit, plus la transition entre les anciens et les nouveaux vecteurs sera fluide.
(À ce stade, vous constaterez que la voiture braquera même si elle est immobile. Pour éviter cela, multipliez steer_angle
par current_speed / max_speed
, où max_speed
est une constante définie par vous.)
En mouvement
Nous allons maintenant appliquer l'accélération et déplacer la voiture d'un certain nombre de pixels en fonction de sa vitesse, de son accélération et de sa direction. Nous voudrons également limiter la vitesse de la voiture afin qu'elle ne se déplace pas infiniment vite.
current_speed = velocity_vector.norm()
if (current_speed < max_speed)
{
velocity_vector += acceleration_vector * time_since_last_frame
}
position_vector += velocity_vector * time_since_last_frame
Votre voiture glisse maintenant
Si j'ai raison, votre voiture devrait maintenant sembler glisser quand vous tournez comme si elle était sur la glace. En effet, il n'y a pas de friction. Sur une vraie voiture, il y a un frottement latéral élevé (dû au fait que les roues ne peuvent pas tourner latéralement: P).
Vous devrez réduire la vitesse latérale. En ne la réduisant pas complètement, vous pouvez également donner l'impression que la voiture dérive.
lateral_velocity = right_vector * dot(velocity_vector, right_vector)
lateral_friction = -lateral_velocity * lateral_friction_factor
Puisque nous parlons de friction, vous voudrez peut-être également avoir une force (de friction) qui réduit votre vitesse de telle sorte que lorsque vous arrêtez d'accélérer, votre voiture s'arrêtera finalement.
backwards_friction = -velocity_vector * backwards_friction_factor
Votre code pour déplacer la voiture devrait maintenant ressembler à ceci:
// Friction should be calculated before you apply the acceleration
lateral_velocity = right_vector * dot(velocity_vector, right_vector)
lateral_friction = -lateral_velocity * lateral_friction_factor
backwards_friction = -velocity_vector * backwards_friction_factor
velocity_vector += (backwards_friction + lateral_friction) * time_since_last_frame
current_speed = velocity_vector.norm()
if (current_speed < max_speed)
{
velocity_vector += acceleration_vector * time_since_last_frame
}
position_vector += velocity_vector * time_since_last_frame
Notes de clôture
J'ai mentionné comment appliquer le lerping à la direction; Je pense que vous devrez peut-être faire la même chose pour l'accélération et éventuellement pour l'angle de braquage également (vous devrez stocker leurs valeurs de l'image précédente et lerp de cela). De plus, tous les vecteurs relatifs à la voiture (avant, droite, haut) doivent être de longueur 1.
De plus, le frottement est un peu plus compliqué que je ne l'ai montré ici. Vous devez toujours vous assurer que sa longueur n'est jamais supérieure à celle de l'accélération nécessaire pour faire s'arrêter la voiture (sinon le frottement ferait bouger la voiture dans le sens inverse). Vous devriez donc avoir quelque chose comme:
dt = time_since_last_frame
backwards_friction.resize(min(backwards_friction.norm(), velocity_vector.norm() / dt))
lateral_friction.resize(min(lateral_friction.norm(), lateral_velocity.norm() / dt))