IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Physique Discussion :

Roulement d'une balle sur un plan incliné


Sujet :

Physique

  1. #1
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2006
    Messages
    94
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2006
    Messages : 94
    Points : 64
    Points
    64
    Par défaut Roulement d'une balle sur un plan incliné
    Bonjour !

    Dans mon projet de flipper, à force que la balle rebondisse sur le segment, avec les chocs sa vitesse va devenir nulle.
    Elle sera "bloquée" sur le segment sans vitesse.
    Or la gravitation doit faire son effet : la balle doit rouler sur le segment.

    [il doit me manquer des informations dans les équations vectorielles]

    t0 : la balle est sur le segment sans vitesse initiale.
    t1 : la gravitation fait son effet

    a) Déclarations
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    this->m_t = 0;
    float f = G*SINA * cos(M_PI/2 - L->m_A);
    this->m_PI = new CVector(0,0, f * cos(L->m_A), f * sin(L->m_A));
    b) On fait évoluer la position de la balle dans le temps
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    this->m_X0 + this->m_PI->v_X * m_t; 
    this->m_Y0 + this->m_PI->v_Y * m_t;
    t2 : La balle fait quelques millimètres à l'écran et franchit le segment
    alors qu'il n'y a que ces vecteurs qui feront bouger la balle et sachant que lorsque la balle roule, elle est toujours en "colision" avec le segment. voir bout de code qui suit : le booléen Rolling permet de savoir si il faut faire rouler la balle et change si la balle n'est plus en colision avec la ligne.

    En gros, voici la routine globale de gestion de colisions :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
    // L = le segment que la balle rencontre - this = balle //
                            // Si la balle a bougé alors il y a toujours un mouvement //
                            // ou si on a rencontré un autre plan incliné qui empecherait le roulement //
                            if( ( (this->m_X0 != this->m_X || this->m_Y0 != this->m_Y) && !this->Rolling)
                                    || (this->Rolling && L != this->pLR) )
                                    pAll->Rebond(L, this);
                            // Si on reste au même endroit alors on va commencer à rouler //
                            else if (cos(L->m_A) != 0 && sin(L->m_A) != 0 && !this->Rolling)
                            {
                                    this->m_t = 0;
     
                                    float f = G*SINA * cos(M_PI/2 - L->m_A);
     
                                    this->Rolling = true;
                                    // pLR = pointeur sur segment recontré // 
                                    this->pLR = L;
     
                                    this->m_PI = new CVector(0,0, f * cos(L->m_A), f * sin(L->m_A));
                            }
                            // Sinon la balle est sur un plan incliné (non horizontal) -> elle roule //
                            else if (this->Rolling)
                                    pAll->Glissements(L, this);
                            // sinon on reste fixe sans bouger //
                            else this->m_t = 0;
     
                            // On réajuste les coordonnées Vx Vy du vecteur vitesse //
                            this->D2(this->m_V, this->m_A);
    Fonctions :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
    void SMath::Rebond(CLine *pL, CBall *pBall)
    {
            #define VF 0.3
            float K = 0;
            // Angle entre la dernière position et le lieu de rebond //
            if (abs(pBall->m_X-pBall->m_X0) != 0)
                    K = abs(pBall->m_Y-pBall->m_Y0) / abs(pBall->m_X-pBall->m_X0);
            pBall->m_A = atan (K);
            // Nouvelle angle avec rebond //
            pBall->m_A = - pBall->m_A + 2*pL->m_A;
     
            // Absorption du choc de la bille avec la ligne rencontrée //
            if (pBall->m_V - VF < 0)
                    pBall->m_V = 0;
            else pBall->m_V -= VF;
     
            pBall->m_t = 0;
            // Les valeurs fixes sont récupérés //
            pBall->m_X0 = pBall->m_X;
            pBall->m_Y0 = pBall->m_Y;
    }
     
    void SMath::Glissements(CLine *pL, CBall *pBall)
    {
            // Si la balle roule sur un plan incliné //
            pBall->m_X = pBall->XR();
            pBall->m_Y = pBall->YR();
    }
    J'espère que vous aurez assez de temps pour comprendre mon problème
    Merci

  2. #2
    Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2006
    Messages
    94
    Détails du profil
    Informations personnelles :
    Sexe : Homme

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2006
    Messages : 94
    Points : 64
    Points
    64
    Par défaut
    Changement de tactique : après m'être informé plus en détails, j'ai interrompu le "cas par cas" en découpant la chute libre et le roulement sur plan incliné.

    Mon code prend beaucoup moins de lignes et est beaucoup plus efficace
    J'ai enlevé et rajouté quelques variables.
    Mais il reste encore un problème : colision avec le segment.
    Le test est le suivant : on recupère le x1/y1 et x2/y2 du segment.
    On fait une rotation du repère de sorte que le segment soit horizontal : ceci nous facilitera la tache pour savoir si oui ou non le centre de gravité de la balle est dans ce rectangle.
    Le rectangle correspond au segment mais muni de l'épaisseur du rayon pour détecter la colision.

    Lorsque le test est positif ma balle rebondit lorsqu'elle touche le rectangle mais sans la rotation...
    (le test correspon à la fonction colisiondroite)

    Si vous pouviez me donner un petit coup de pouce .
    Je sais que des problèmes avec beaucoup de code sont enervants à résoudre .

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
     
    void CBall::Move()
    {
            float V = pAll->AbsVF(this->V_ini->v_X, this->V_ini->v_Y);
            // On definit les vecteurs d'acceleration //
            this->Obstacles();
     
            float ADDX = this->V_ini->v_X * dt + 0.5 * this->V_acc->v_X * dt * dt;
            float ADDY = this->V_ini->v_Y * dt + 0.5 * this->V_acc->v_Y * dt * dt;
            // V = V0 + a * t //
            this->V_ini->v_X += dt * this->V_acc->v_X;
            this->V_ini->v_Y += dt * this->V_acc->v_Y;
     
            this->m_X = this->m_X0 + ADDX;
            this->m_Y = this->m_Y0 + ADDY;
     
            this->m_X0 = this->m_X;
            this->m_Y0 = this->m_Y;
    }
     
    bool CBall::Obstacles()
    {
            int nOb = pAll->pPF->m_Ob.size();
     
            for (int i = 0; i < nOb; i++)
            {
                    CObstacle *OB = &pAll->pPF->m_Ob[i];
                    CLine *L = pAll->pPF->m_Ob[i].ToucheLigne(this);
                    // Si la balle touche la ligne vérifiée //
                    if (L != NULL)
                    {
                            this->V_acc->v_X = G * sin(L->m_A);
                            this->V_acc->v_Y = G * cos(L->m_A);
     
                            double ANGLE = M_PI_2;
     
                            if (this->V_ini->v_X != 0)
                                    ANGLE = atan(this->V_ini->v_Y / this->V_ini->v_X);
     
                            float V = pAll->AbsVF(this->V_ini->v_X, this->V_ini->v_Y);
     
                            float DegA = ANGLE;
                            float DegAl = L->m_A;
     
                            float Diff = sqrt(pow(DegA - DegAl, 2));
     
                            // CADRAN 1  X(+) Y(+) //
                            if (this->V_ini->v_X >= 0 && this->V_ini->v_Y >= 0)
                                    ANGLE = -ANGLE + 2 * L->m_A;
                            // CADRAN 2  X(-) Y(+) //
                            if (this->V_ini->v_X < 0 && this->V_ini->v_Y >= 0)
                                    ANGLE = -ANGLE + 2 * L->m_A - M_PI;
                            // CADRAN 3  X(-) Y(-) //
                            if (this->V_ini->v_X < 0 && this->V_ini->v_Y < 0)
                                    ANGLE = -ANGLE + 2 * L->m_A - M_PI;
                            // CADRAN 4  X(+) Y(-) //
                            if (this->V_ini->v_X >= 0 && this->V_ini->v_Y < 0)
                                    ANGLE = -ANGLE + 2 * L->m_A;
     
                            this->V_ini->v_X = cos(ANGLE) * V;
                            this->V_ini->v_Y = sin(ANGLE) * V;
     
                            if (Diff < 0.25) // Moins de 15° la bille se mettra à rouler //
                            {
                                    this->V_ini->v_Y = 0;
                            }
     
                            return true;
                    }
                    else L = NULL;
            }
     
            this->V_acc->v_X = 0;
            this->V_acc->v_Y = G;
     
            return false;
    }
     
    CLine *CObstacle::ToucheLigne(CBall *pBall)
    {
            // Si ce n'est pas un cercle
            if (!this->m_Circle)
            {
                    int Size = this->m_Lim.size();
                    // On cherche la colision dans l'obstacle
                    for (int i = 0; i < Size; i++)
                    {
                            // Checking colision with segments //
                            if (pAll->ColisionDroite(pBall, &this->m_Lim[i], Rayon))
                                    return &this->m_Lim[i];
                    }
            }
            return NULL;
    }
     
    bool SMath::ColisionDroite(CBall *pB, CLine *pL, int R)
    {
            // On réapplique les coordonnées réels pour les coordonnées de la balle //
            float XN = pB->m_X * 700;
            float YN = pB->m_Y * 700;
            // On applique la rotation //
            float A = pL->m_A * -1;
     
            float X = (XN+R - pL->m_X1) * cos(A) - (YN+R - pL->m_Y1) * sin(A);
            float Y = (XN+R - pL->m_X1) * sin(A) + (YN+R - pL->m_Y1) * cos(A);
     
            float X1 = 0;
            float Y1 = 0;
     
            float X2 = (pL->m_X2 - pL->m_X1) * cos(A) - (pL->m_Y2 - pL->m_Y1) * sin(A);
            float Y2 = (pL->m_X2 - pL->m_X1) * sin(A) + (pL->m_Y2 - pL->m_Y1) * cos(A);
     
            // On obtient une droite horizontale //
            // On fait mtn le test //
            return this->ColisionPoint(X, Y, X1-R, Y1-R, X2+R, Y2+R);
    }
     
    bool SMath::ColisionPoint(float x, float y, float x1, float y1, float x2, float y2)
    {
            if (x > x2) return false;
            if (x < x1) return false;
            if (y < y1) return false;
            if (y > y2) return false;
            return true;
    }

Discussions similaires

  1. [WD14] Ouvrir une fenêtre sur un plan
    Par Aladin699 dans le forum WinDev
    Réponses: 7
    Dernier message: 16/04/2010, 16h03
  2. Recherche et affichage d'une requête sur un plan
    Par illidan05 dans le forum Flash
    Réponses: 0
    Dernier message: 26/07/2009, 09h57
  3. [Java3D] Afficher une grille sur le plan
    Par akito dans le forum 3D
    Réponses: 5
    Dernier message: 23/03/2007, 17h30
  4. Rebond d'une balle sur un sol incliné
    Par franco01 dans le forum Algorithmes et structures de données
    Réponses: 18
    Dernier message: 05/02/2006, 01h20
  5. Réponses: 3
    Dernier message: 29/06/2005, 14h29

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo