SFML - Trajectoire d'un projectile

Le problème exposé dans ce sujet a été résolu.

Bonjour,

Actuellement je m’amuse un peu avec la SFML et j’essaye de réaliser une trajectoire parabolique lors d’un lancé de flèche par exemple.

Pour commencer, je récupère l’angle (que je vais appeler a dans le reste du texte) de tir de mon personnage grâce à atan. Ensuite j’incrémente la position de mon projectile avec cos(a) et sin(a). Donc jusque là, tout est OK, le projectile pars dans la bonne direction.

Cependant, j’aimerai donner un côté réaliste à la chose en appliquant une gravité progressive, qui viendrait petit à petit ralentir mon projectile et le faire chuter (en gros une parabole).

Image utilisateur
Image utilisateur

J’ai déjà essayé quelques méthodes qui me paraissait logiques mais qui à priori ne fonctionnent pas. Comme par exemple, ajouter un membre "velocityY" à chacun de mes projectiles, et à chaque update venir décrémenter cette variable à l’aide d’une constante gravity et du temps entre 2 frames. Cette méthode n’a pas fonctionné, et faisait tombé instantanément mes projectiles …

Voici la méthode "Update" de ma classe collection de projectiles:

void Balls::Update(float deltaTime) {
 
  int i = 0;
 
  for (Ball &ball : m_Balls) {
 
    // Pour la balle courante, on ajoute sa vélocité en Y
    ball.SetVelocityY(ball.GetVelocityY() + GRAVITY * deltaTime);
 
    float speed = m_nVelocity * deltaTime;
 
    int x = ball.GetPosition().x + cos(ball.GetAngle()) * speed;
 
    int y = ball.GetPosition().y - sin(ball.GetAngle()) * ball.GetVelocityY();
 
  }
 
}

Voilà, en remerciant déjà ceux qui prendront la peine de me répondre :)

Salut,

Tu vas avoir deux jeux d’équations :

  • un pour faire évoluer la vitesse,
  • un pour faire évoluer la position.

Pour faire évoluer la vitesse, tu as la composante en X qui est une constante (vxv_{x} ne change pas si tu n’ajoutes pas de frottements). Je crois comprendre qu’il s’agit de la composante en X de speed ici, même si je ne comprends pas ton m_nVelocity.

Pour la composante en Y, l’équation doit avoir la forme suivante :

vy,n=vy,n1gΔtv_{y,n} = v_{y, n-1} - g \Delta t

En fonction de l’orientation de ton repère, tu vas avoir besoin de changer le signe, peut-être.

Maintenant, faire évoluer la position ne dépend que de la vitesse et du pas de temps. Tu dois avoir quelque chose de la forme :

xn=xn1+vx,nΔtx_n = x_{n-1} + v_{x,n} \Delta t yn=yn1+vy,nΔty_n = y_{n-1} + v_{y,n} \Delta t

Comme tu as calculé les vitesses à l’étape d’avant, tu les connais.

Dans ton code, il y a des problèmes, comme le fait que tu additionnes des vitesses avec des positions (sauf que speed n’est probablement même pas une vitesse). Il te manque des Δt\Delta t à certains endroits. Aussi, je ne vois pas pourquoi tu fais intervenir l’angle dans le calcul. En pratique, seule la vitesse initiale a besoin de connaître l’angle pour être décomposée sur les coordonnées. Après, chaque coordonnée vit sa vie.

J’ai bien envie de faire de l’autopromotion en te conseillant de lire ce tutoriel. Dans ton cas, tout part de l’équation (vectorielle) suivante :

dvdt(t)=g\frac{\mathrm d \mathbf v}{\mathrm d t}(t) = - \mathbf g

+3 -0

Salut Aabu !

Merci beaucoup pour ta réponse qui m’a permis de résoudre le problème !

void Balls::Update(float deltaTemps) {

    for (Ball &ball : m_Bullets) {

                // Permet de recalculer la vitesse en fonction du temps écoulé entre deux frames
        float speed = m_nVelocity * deltaTemps;

                // Réduit l'accélération en Y
        ball.SetVelY(ball.GetVelY() - m_Gravity * deltaTemps);

                // Attribution de la nouvelle position
        ball.SetDirection(ball.GetPosition().x + speed, ball.GetPosition().y - ball.GetVelY());

    }

}

Et merci aussi pour le lien, je vais aller y jeter un coup d’oeil, je crois que j’en ai bien besoin :)

Je passe en résolu

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte