Je cherche à créer un mouvement de voiture réaliste en utilisant des vecteurs

12

J'ai jeté un coup d'œil sur la façon de le faire et j'ai trouvé ce http://www.helixsoft.nl/articles/circle/sincos.htm J'ai essayé, mais la plupart des fonctions qui ont été montrées ne fonctionnaient pas. parce qu'ils n'existaient pas. J'ai examiné les fonctions cos et sin, mais je ne comprends pas comment les utiliser ou comment faire fonctionner correctement le mouvement de la voiture à l'aide de vecteurs. Je n'ai pas de code car je ne sais pas quoi faire, désolé.

Toute aide est appréciée.

ÉDITER:

J'ai des restrictions que je dois utiliser le moteur TL pour mon jeu, je ne suis pas autorisé à ajouter aucune sorte de moteur physique. Il doit être programmé en c ++. Voici un échantillon de ce que j'ai obtenu en essayant de suivre ce qui a été fait dans le lien que j'ai fourni.

if(myEngine->KeyHeld(Key_W))
    {
        length += carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_S))
    {
        length -= carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_A))
    {
        angle -= carSpeedIncrement;
    }
    if(myEngine->KeyHeld(Key_D))
    {
        angle += carSpeedIncrement;
    }

    carVolocityX = cos(angle);
    carVolocityZ = cos(angle);

    car->MoveX(carVolocityX * frameTime);
    car->MoveZ(carVolocityZ * frameTime);
bobthemac
la source
Consultez ce site pour connaître les
MichaelHouse
Vous devez définir un "mouvement de voiture réaliste"
Maik Semder
1
Je suppose que votre angle vient du volant, peut-être. La longueur doit être la magnitude de votre vitesse. Ainsi , le dernier extrait de code pourrait être quelque chose sur les lignes de: carVecloityX = length* cos(angle);, carVelocityZ = length *sin(angle);, à part cela, s'il vous plaît dire ce que votre entrée est et comment la voiture doit se comporter. À l'heure actuelle, il devrait se diriger dans le plan du sol, mais encore une fois, ce n'est pas du tout général. Là, vous venez de nous faire une étape d'intégration brute d'Euler ..
teodron

Réponses:

23

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_anglepar current_speed / max_speed, où max_speedest 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))
Paul Manta
la source
Wow, c'est une excellente réponse!
ezolotko
0

À en juger par votre question, je vais supposer que vous êtes relativement nouveau dans la programmation (ce qui est a-ok btw!). Je suggérerais d'utiliser les cadres existants car la simulation de voiture réaliste est l'un des aspects les plus difficiles de la physique.

Vous n'avez pas mentionné de restrictions 2D / 3D, donc je vais aller de l'avant et vous suggérer de télécharger Havok SDK (gratuit pour une utilisation non commerciale) et d'obtenir une démo simple et opérationnelle (ils ont en fait des démos qui sortent de la boîte [obtenir compilé sur votre système, tout le code est là], vous n'avez rien à faire pour le compiler ... ouvrez simplement le projet et appuyez sur build).

Une fois que vous aurez une idée des aspects cachés de la physique automobile (bien que vous ne verrez pas la mise en œuvre réelle de la physique, qui est cachée, vous pourrez voir les interfaces), je pense que vous serez dans une meilleure position pour bien faire les choses quand vous commencez par vous-même.

J'ai également posé une question similaire il n'y a pas si longtemps. Les liens qu'il contient peuvent également vous aider. Et voici un autre lien .


Après avoir regardé votre montage, il semble que vous cherchiez simplement à changer la vitesse de la voiture en fonction des angles calculés (ce n'est pas réaliste, vous devriez donc changer la question d'origine pour refléter cela). Si les angles font partie de la question (que vous ne pouvez pas changer) et que vous devez utiliser les angles pour calculer la nouvelle vitesse, alors allez avec ce que @teodron a mis dans les commentaires.

Une autre façon consiste à utiliser uniquement des vecteurs. Il existe plusieurs approches utilisant des vecteurs, je vais en présenter une.

Une vitesse est une direction * magnitude (où la magnitude est la vitesse et la direction est un vecteur normalisé). Calculez la vitesse et la direction actuelles de la voiture. Prenez la direction et ajoutez-y un vecteur (appelons-le D') qui lui est perpendiculaire. Cela changera la vitesse de la voiture. Aucun angle avec lequel jouer (bien que vous puissiez utiliser des angles pour déterminer la longueur du vecteur perpendiculaire qui peut être votre facteur de rotation [voir ci-dessous])

Comment calculerD' : Pour trouver le vecteur perpendiculaire, prenez la direction de la vitesse d'origine, traversez-la avec le vecteur direction venant vers l'écran où l'ordre dans lequel vous traversez les vecteurs détermine la direction du vecteur perpendiculaire. Multipliez ensuite ce facteur perpediculaire avec un facteur de virage qui détermine la vitesse à laquelle la voiture tourne.

Samaursa
la source
Je le ferais, mais je ne suis pas autorisé à utiliser un moteur physique, le jeu est en 3D et tout ce que je dois changer, c'est les vecteurs X et Z, j'ai juste besoin de savoir ce qu'ils sont.
bobthemac
@bobthemac: Est-ce une question de devoirs? Si oui, modifiez votre question pour souligner les restrictions que vous avez et peut-être publier du code pertinent afin que nous ayons quelque chose à construire. Btw, le dernier lien peut être ce que vous recherchez pour comprendre la fonctionnalité.
Samaursa
J'ai ajouté les informations que vous avez demandées et j'ai regardé les liens fournis mais je ne comprends toujours pas.
bobthemac
@bobthemac: Voir mon montage
Samaursa