Bases d'un moteur physique (partie 1)

Voir le sujet précédent Voir le sujet suivant Aller en bas

Bases d'un moteur physique (partie 1)

Message par Akabane87 le Sam 9 Avr - 21:31

Voici donc la 1ère partie de mon tuto sur les bases d'un moteur physique.

Un moteur physique a pour but de recréer les lois de la mécanique newtonienne et de les appliquer à des objets physiques dans une scène 2D ou 3D. Dans le tuto qui suit je vais prendre l'exemple de la 2D mais il s'applique de la même manière à la 3D.

Tout d'abord revenons sur les bases d'une boucle de jeu codée proprement. On a normalement 3 parties principales dans une boucle infinie comme le montre le code qui suit :
Code:

while(continuer)
{
  float deltaTemps = GetDeltaTemps();// on récupère le temps écoulé depuis la dernière itération (avec un timer)

  Controls();// on effectue les actions relatives à l'appui des touches

  Update(deltaTemps);// on met à jour les objets de la scene
 
  Render();// on affiche tout le bazar
}

La fonction Controls() mettra à jour le ou les objets contrôlés par les touches
La fonction Update() contiendra tous les calculs de physique
La fonction Render() va simplement afficher tous les objets

La fonction Update() aura besoin de connaître le temps écoulé depuis le dernier passage afin de faire ses calculs physiques, d'où le timer implicitement utilisé derrière la fonction GetDeltaTemps().

Tout d'abord on va avoir besoin d'une structure Vec2D qui contiendra juste 2 float x et y, ainsi que de fonctions de math sur des vecteurs 2D comme la somme, la différence, la multiplication par un scalaire et pis c'est tout Razz . Pour la suite je mettrai des +, - et * avec des Vec2D pour simplifier l'écriture mais il faudra en vrai utiliser les fonctions de math crées pour ça (ou alors surcharger les opérateurs si on est en c++).

On aura ensuite besoin d'une structure Objet2D qui contient :
Vec2D Position;
Vec2D Vitesse;
Vec2D SommeForces;
float Masse;

et tous les autres trucs dont vous pourrez avoir besoin pour votre jeu.

Le fonctionnement de la méthode Update() est ensuite assez simple :
On met à jour les variables Vitesse et Position à partir de la SommeForces.

Le calcul pour passer de la somme des forces à la vitesse est simple :
Code:

MonObjet2D.Vitesse += (deltaTemps/MonObjet2D.Masse) * MonObjet2D.SommeForces;

et ensuite pour passer de la vitesse à la position c'est encore plus simple :
Code:

MonObjet2D.Position += deltaTemps * MonObjet2D.Vitesse;

Et enfin on termine en mettant MonObjet2D.SommeForces à 0 pour signifier que toutes les forces ont été prises en compte à cette frame.

Et on fait ça pour tous les objets de la scène. Si l'on veut appliquer la gravité à tous les objets, on pourra ajouter la force de gravité dans l'Update pour chaque objet juste avant de calculer la vitesse :
Code:

Vec2D force;
force.x = 0.0f;
force.y = 9.8f;//si y est vers le bas
MonObjet2D.SommeForces += force;

Pour les mathématiciens en herbe qui sont en train de hurler intérieurement "à l'arnaque !!! C'est quoi cette intégration frauduleuse !", il s'agit bien d'une approximation du type DeltaVitesse = DeltaPosition / DeltaTemps qui est d'autant plus juste que DeltaTemps est petit (ce qui sera le cas vu qu'on tourne au minimum à 30 fps (donc 1/30 s) quand tout va bien). CQFD Razz

Une fois calculée la position et la vitesse de tous nos objets ben on a plus qu'à tout afficher avec la fonction Render() qui va simplement afficher tous les objets aux positions Position.x, Position.y (on pourra peut être faire une mise à l'échelle pour éviter d'avoir 1pixel=1m et du coup des vitesses en pixels/s visuellement lentes).

On arrive enfin à la fonction Controls()... Au lieu de modifier directement les positions ou la vitesse de nos objets, on va à la place ajouter des forces à la somme des forces pour faire avancer nos objets dans une direction donnée.
Cela fonctionne exactement comme pour la gravité. Par exemple pour aller dans la direction du stick :
Code:

Vec2D force;
force.x = (float)StickX/128.0f;
force.y = -(float)StickY/128.0f;// puisque l'axe Y est vers le bas
MonObjet2D.SommeForces += force*100.0f;// faut quand même pousser un minimum ^^ (100N pendant 80ms environ c'est pas tant que ça :p )

Et hop magie lors de l'appel de la fonction Update() sur cet objet, la position sera mise à jour et l'objet avancera dans la direction donnée par le stick cheers .
avatar
Akabane87
Admin

Messages : 45
Date d'inscription : 30/07/2010

Voir le profil de l'utilisateur http://dreamraiser.forumactif.com

Revenir en haut Aller en bas

Voir le sujet précédent Voir le sujet suivant Revenir en haut

- Sujets similaires

 
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum