Moteur physique

Jackyzgood Messages postés 26 Date d'inscription mercredi 17 septembre 2008 Statut Membre Dernière intervention 6 mars 2010 - 25 oct. 2009 à 13:22
Jackyzgood Messages postés 26 Date d'inscription mercredi 17 septembre 2008 Statut Membre Dernière intervention 6 mars 2010 - 6 nov. 2009 à 12:14
Bonjour à tous !

J'essaye actuellement de créer une fonction qui me gère des trajectoires simple dans un champ de pesanteur avec rebond. Mon problème ne vient pas de la physique, j'ai déjà fait une trajectoire en pré-calculé, aucun soucis.

    while(continuer)
    {
                Objet.temps = SDL_GetTicks();
                
                SDL_FillRect(ecran, NULL, SDL_MapRGB(ecran->format, 255, 255, 255));
                gestion_des_evenements (&event, &Evenements, &continuer);

                SDL_BlitSurface(marqueur, NULL, ecran, &(Objet.position_affichage));

                SDL_Flip(ecran);
                
                //limitation du nombre de boucle dans le temps
                if(SDL_GetTicks() - Objet.temps < 20)
                {SDL_Delay(20 -(SDL_GetTicks() - Objet.temps));}
                
                //comme le nombre de boucle est limite on est sur que delta_T ne sera pas nul
                Objet.delta_T = SDL_GetTicks() - Objet.temps;
                
                //Par definition a = dV/dt <=> a * dt = dV
                Objet.delta_vitesse.y = Objet.acceleration.y * Objet.delta_T;
                //la vitesse sera la somme des variations de vitesse
                Objet.vitesse.y += Objet.delta_vitesse.y;
                
                /*par definition V = dOM/dt, ou OM est la position de l'objet M par rapport a l'origine O.
                on en deduit : dOM = v * dt           */
                Objet.delta_position.y = Objet.vitesse.y * Objet.delta_T;
                
                //la position sera la somme des variations de position
                Objet.position_affichage.y += Objet.delta_position.y;
                
                /*gestion d'une collision elastique avec le bas de l'ecran :
                  si l'objet sort de l'ecran (par le bas) alors on lui
                  donne une vitesse oppose ce qui genere le rebond.*/
                if(Objet.position_affichage.y > ecran->h -50)
                {Objet.vitesse.y = -Objet.vitesse.y;}
    }


Voila ma boucle principale, le soucis avec cette boucle c'est que l'objet rebondit plus haut qu'il ne devrait... et je ne vois pas d'où ça peut venir. Si quelqu'un vois ou est mon erreur.

Merci

4 réponses

cs_daddou24 Messages postés 1 Date d'inscription samedi 17 octobre 2009 Statut Membre Dernière intervention 25 octobre 2009
25 oct. 2009 à 18:47
Bonjour,
Essaye une méthode d'intégration plus précise comme l'algorithme de verlet (voir wikipedia), et puis mettre un petit coef (genre 0.9) qui réduit la vitesse de ton mobile aprés un choc.
Bon courage,
Damien.
0
Jackyzgood Messages postés 26 Date d'inscription mercredi 17 septembre 2008 Statut Membre Dernière intervention 6 mars 2010
25 oct. 2009 à 22:57
Merci à toi pour ta réponse. J'ai cherché l'algorithme de Verlet et il y à quelques passage que j'ai pas compris, notamment sur l'ajout des termes de degrés 2.

http://upload.wikimedia.org/math/c/5/b/c5bf2e37ccac3265987017e65f1228d2.png

Dans cette formule (si j'ai bien compris)

le terme x(t + delta_t) correspond à la position suivante.

Le terme v(t)delta_t correspond au déplacement durant le temps delta_t.

Le terme a(t)delta_t²/2 est également équivalent au déplacement durant le temps delta_t.

Et c'est ça que je ne comprends pas. Pourquoi faire apparaitre 2 fois le déplacement ?
0
cs_juju12 Messages postés 966 Date d'inscription samedi 3 avril 2004 Statut Membre Dernière intervention 4 mars 2010 4
26 oct. 2009 à 15:58
C'est pas directement la formule, ça, c'est simplement un développement limité.
Les formules sont également ici, peut-être plus clair :
http://en.wikipedia.org/wiki/Leapfrog_integration

le principe est de calculer un coup la vitesse et un coup la position.
L'avantage de ce schéma est la conservation de l'énergie totale.
0
Jackyzgood Messages postés 26 Date d'inscription mercredi 17 septembre 2008 Statut Membre Dernière intervention 6 mars 2010
6 nov. 2009 à 12:14
J'ai réussi à faire ce que je voulais

http://www.youtube.com/watch?v=1CNn3VX9RkA&feature=player_embedded

Comme vous pouvez le voir sur cette vidéo, quelques rares points arrivent à traverser lignes avec lesquelles ils rentrent en collision.

Pour gérer les collisions, je chronomètre la boucle principale, je calcule la position suivante et crée 2 vecteurs, avec les 2 points et une extrémité d'une droite. Ensuite je regarde les angles entre la droite et le vecteur position, puis avec le vecteur position suivante. S'il y a changement de signe c'est que le point va traverser la droite, c'est à ce moment là que je déclenche la collision.

Voila la fonction qui gère les collision, je ne vois pas ou j'ai pu commettre une erreur et pourquoi certain point arrive a se faufiler entre les conditions.


#include "structures.h"

int fonction_collision(struct structure_objet_physique *Objet, struct Structure_geometrique_ligne Ligne)
{
     //creation du vecteur représantant la ligne
     struct Structure_geometrie_vecteur Vecteur_ligne;
     Vecteur_ligne.x = 0;
     Vecteur_ligne.y = 0;
     
     fonction_coordonnees_vecteur(&Vecteur_ligne, Ligne.x[0], Ligne.y[0], Ligne.x[1], Ligne.y[1]);    
    
    
     //création du vecteur position par rapport a la ligne
     struct Structure_geometrie_vecteur Vecteur_position_relative;
     Vecteur_position_relative.x = 0;
     Vecteur_position_relative.y = 0;
     
     fonction_coordonnees_vecteur(&Vecteur_position_relative, Ligne.x[0], Ligne.y[0], (*Objet).Vecteur_position.x, (*Objet).Vecteur_position.y);

     //calcul de la position suivante
     struct Structure_geometrie_vecteur Vecteur_position_relative_suivante;
     Vecteur_position_relative_suivante.x = 0;
     Vecteur_position_relative_suivante.y = 0;
     
     fonction_coordonnees_vecteur(&Vecteur_position_relative_suivante, Ligne.x[0], Ligne.y[0], (*Objet).Vecteur_position_suivante.x, (*Objet).Vecteur_position_suivante.y);

     //calcul de la difference de position
     struct Structure_geometrie_vecteur Vecteur_delta_position;
     Vecteur_delta_position.x = 0;
     Vecteur_delta_position.y = 0;
     
     fonction_coordonnees_vecteur(&Vecteur_delta_position, (*Objet).Vecteur_position.x, (*Objet).Vecteur_position.y, (*Objet).Vecteur_position_suivante.x, (*Objet).Vecteur_position_suivante.y);
     
     
     //calcul de l'angle entre les vecteurs
     double angle_initial = fonction_angle_entre_vecteur(&Vecteur_ligne, &Vecteur_position_relative),
     angle_final = fonction_angle_entre_vecteur(&Vecteur_ligne, &Vecteur_position_relative_suivante),
     angle_delta_position = fonction_angle_entre_vecteur(&Vecteur_ligne, &Vecteur_delta_position);
     
     
     if( ((angle_initial > 0 && angle_final < 0) || (angle_initial < 0 && angle_final > 0))
     && fonction_produit_scalaire(&Vecteur_ligne, &Vecteur_position_relative) > 0
     && fonction_produit_scalaire(&Vecteur_ligne, &Vecteur_position_relative) < fonction_norme_vecteur(&Vecteur_ligne) * fonction_norme_vecteur(&Vecteur_ligne))
     {
             (*Objet).Vecteur_position_initiale.x = (*Objet).Vecteur_position.x;
             (*Objet).Vecteur_position_initiale.y = (*Objet).Vecteur_position.y;
             
             (*Objet).Vecteur_vitesse_initiale.x = 0.7*(*Objet).Vecteur_vitesse.x;
             (*Objet).Vecteur_vitesse_initiale.y = 0.7*(*Objet).Vecteur_vitesse.y;             
             
             fonction_rotation_vecteur(&((*Objet).Vecteur_vitesse_initiale), (-2*angle_delta_position));
             
             (*Objet).temps_initial = SDL_GetTicks();
             return 1;
     }
     else {return 0;}
}
0
Rejoignez-nous