Ma balle chute un peu trop vite

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

Bonjour,

J'ai réalisé aujourd'hui un exercice de physique visant à calculer la trajectoire de la balle dans un référentiel terrestre (et donc galiléen). Je me suis dit qu'il serait amusant de créer un simulateur de lancer de balle grâce à un moteur de jeu. Mon choix c'est porté sur mon nouveau jouet, LÖVE. Voici mon fichier qui gère les mouvements de la balle :

 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
function init_ball()
    ball = {
        radius = 10,
        velocity = {
            x = 100,
            y = 100
        },
        color = { 255, 255, 255 }
    }

    ball.position = {
        x = ball.radius,
        y = game.height - ball.radius,
        start = {} -- Position de la balle quand l'utilisateur presse space (pour savoir à quelle hauteur la balle est lancée)
    }
end

-- Bouge manuellement la balle sur l'axe des y, si la barre espace est pressée, on met le jeu sur start empêchant tout déplacement manuel de la balle
function move_ball(dt)
    if love.keyboard.isDown("up") or love.keyboard.isDown("z") then
        ball.position.y = ball.position.y - (ball.velocity.y * dt)
    end

    if love.keyboard.isDown("down") or love.keyboard.isDown("s") then
        ball.position.y = ball.position.y + (ball.velocity.y * dt)
    end

    if love.keyboard.isDown("space") then
        ball.position.start.y = ball.position.y -- On sauvegarde la position de la balle avant de la lancer
        game.start = true
    end
end

-- Calcule la nouvelle position de la balle une fois la simulation lancée
function throw_ball(dt)
    ball.position.x = ball.position.x + (ball.velocity.x * dt)
    ball.position.y = ball.position.y - (-0.5 * game.constants.g * (ball.position.x/(ball.velocity.x * dt))^2 + ball.position.start.y)
end

-- Empêche la balle de sortir de l'écran
function block_ball()
    if (ball.position.y - ball.radius) < 0 then
        ball.position.y = ball.radius
    elseif (ball.position.y + ball.radius) > game.height then
        ball.position.y = game.height - ball.radius
    end
end

-- Calcule la position de la balle
function update_ball(dt)
    if game.start then -- On ne calcule la position de la balle qui si l'utilisateur à appuyé sur "space" (la variable game.start passe alors à true)
        throw_ball(dt)
    else -- Sinon on autorise l'utilisateur à placer manuellement la balle le long de l'axe y
        move_ball(dt)
    end

    block_ball() -- On empêche la balle de sortir du cadre
end

-- Dessine la balle
function draw_ball()
    love.graphics.setColor(ball.color)
    love.graphics.circle("fill", ball.position.x, ball.position.y, ball.radius, 64)
end

Dès que je presse space, la balle entame un mouvement très rapide (j'ai du filmer mon écran et passer la vidéo au ralenti pour voir ce mouvement) vers le haut et redescend à la même vitesse vers le bas puis elle slide sur cet axe (dû à la fonction block_ball()).

Soit le mouvement est tellement infime qu'il faudrait que je zoom pour pouvoir le voir où alors il y a quelque chose qui m'échappe. En tout cas, merci de votre aide! :)

PS : l'équation paramétrique horaire que j'ai calculé dans mon exercice pour calculer la position de la balle est celle-ci :

$$ x(t) = v_0t\\ y(t) = \frac{-gt^2}{2} + H $$
Ce qui nous donnais :
$$ y(x) = -\frac{1}{2}g(\frac{x}{v_0})^2 + H $$

Avec :

  • $g$ la constante de pesanteur : 9.80665
  • $v_0$ la vitesse initiale de la balle (ici 100 : ball.velocity.x)
  • $H$ la hauteur de lancer de la balle (ball.position.start.y)
+0 -0

Salut,

Dans ton code, tu as fait un mix bizarre entre l'équation paramétrique et ce qui serait une espèce d'intégration de je ne sais quoi.

1
ball.position.y = ball.position.y - (-0.5 * game.constants.g * (ball.position.x/(ball.velocity.x * dt))^2 + ball.position.start.y)

Soit tu utilises directement l'équation paramétrique $y(x)$, soit directement $y(t)$, soit comme pour $x$ tu intègres temporellement $\dfrac{\mathrm dy}{\mathrm dt}$, mais tu ne fais pas un mix des trois.

EDIT : par ailleurs, Löve inclus un moteur physique. Utilise-le au lieu de bricoler tes propres intégrateurs (on ne s'improvise pas ingénieur en méthode numériques de résolution d'EDO :p ) si tu comptes faire un projet plus grand.

+1 -0

on ne s'improvise pas ingénieur en méthode numériques de résolution d'EDO

Rho je voulais juste essayer ! :p Anyway, ce n'est pas un projet du tout, c'est juste que j'avais envie de me coder mon petit simulateur de balle de tennis.

Je ne vois pas trop ce que tu veux dire ici :

Soit tu utilises directement l'équation paramétrique y(x), soit directement y(t), soit comme pour x tu intègres temporellement dydt, mais tu ne fais pas un mix des trois.

J'ai utilisé $y(x)$ non ?

Salut, Je ne connais pas löve, et ce que je vais dire est peut être un peu con, mais ton dt, il est en quelle unité ? Si c'est des millisecondes, il faut pas oublier de tout diviser par 1000 !

Fab

$dt$ est bien en secondes : Time since the last update in seconds (j'avoue avoir crû que c'était la bonne solution :-° ).

Je ne vois pas trop ce que tu veux dire ici :

Soit tu utilises directement l'équation paramétrique y(x), soit directement y(t), soit comme pour x tu intègres temporellement dydt, mais tu ne fais pas un mix des trois.

J'ai utilisé $y(x)$ non ?

Ben non, tu as utilisé un truc un peu bizarre qui serait plutôt $\mathrm dy = -\dfrac 12g\left(\dfrac{x}{v_0\mathrm dt}\right)^2 +H$ (ce qui n'est même pas homogène). Ça n'a rien à voir avec $y(x) = -\dfrac{1}{2}g\left(\dfrac{x}{v_0}\right)^2 + H$.

+0 -0

Aaaaarg oui j'ai compris ! C'est juste moi qui suit bête, il ne faut pas multiplier $v_0$ par $dt$ mais toute l'équation par $dt$! Du coup, ça me donne :

1
ball.position.y = ball.position.y - (-0.5 * game.constants.g * (ball.position.x/ball.velocity.x)^2 + (game.height - ball.position.start.y)) * dt

Beaucoup de boulot pour... ça !

Merci à vous, problème résolu !

Aaaaarg oui j'ai compris ! C'est juste moi qui suit bête, il ne faut pas multiplier $v_0$ par $dt$ mais toute l'équation par $dt$!

What ? o_O Ça marche (enfin, tu as l'illusion que ça marche, mais en fait tu ne résouds pas la bonne équation), mais tu te compliques la vie pour rien. Tu as une équation indépendante du temps, profites-en !

1
ball.position.y = 0.5 * game.constants.g * (ball.position.x/ball.velocity.x)^2 - (game.height - ball.position.start.y)
+0 -0

Ah mais ça ne fonctionne pas sans dt :

Both of these function take dt as an argument. This is a measure of how much time has passed since the last call. We'll multiply our timers by these values to ensure the game runs the same on your friends old laptop that gets 30 fps or your brand new gaming rig that gets 700 fps.


We multiple by dt standing for delta-time or the change in time since the last update call to account for framerate differences between machines.

http://www.osmstudios.com/page/your-first-love2d-game-in-200-lines-part-1-of-3

Je ne comprends pas ton problème, rien ne t'empêche de passer $\mathrm dt$ en argument de ta fonction même si tu ne t'en sers pas dans le calcul, et de toute façon tu as besoin de ce $\mathrm dt$ pour calculer $x(t)$.

+0 -0

La variable $dt$ n'a rien à voir avec le temps que la balle est en vol, en faite elle n'a rien à voir avec la balle.

Oui, j'avais compris, ça n'a juste rien à voir du tout avec ce que je suis en train de te dire. Tu as une équation $\dfrac{\mathrm dx}{\mathrm dt}=v_0$ qui te permet de mettre à jour $x$ à chaque pas de temps en utilisant $\mathrm dt$. Tu as aussi une équation qui te donne $y$ pour n'importe quelle valeur de $x$ valable à n'importe quel instant et quelque que soit le temps $\mathrm dt$ écoulé depuis la dernière mise à jour. Tu peux donc utiliser cette seconde équation pour calculer directement $y$ à partir de $x$ (une fois ce dernier calculé avec le $\mathrm dt$) sans avoir à intégrer quoique ce soit.

Voici ce que j'obtiens en enlevant $dt$

Il faut le code complet de ta fonction throw_ball, sinon c'est difficile de savoir ce que tu as fais ou pas.

+0 -0

Voici ma fonction throw_ball sans le $dt$ :

1
2
3
4
5
6
7
8
9
function throw_ball(dt)
    ball.position.x = ball.position.x + (ball.velocity.x * dt)
    ball.position.y = ball.position.y - (-0.5 * game.constants.g * (ball.position.x/ball.velocity.x)^2 + (game.height - ball.position.start.y))

    if ball.position.y + ball.radius > game.height then
        ball.velocity.x = 0
        ball.position.y = game.height - ball.radius
    end
end

Ah je pense avoir compris. Ma seconde équation n'utilise seulement la position de $x$ pour déterminer la position de $y$ donc pas besoin de $dt$. Mais ce que je ne comprend pas, c'est que ça ne fonctionne pas sans. En rajoutant :

1
print((-0.5 * game.constants.g * (ball.position.x/ball.velocity.x)^2 + (game.height - ball.position.start.y)))

au milieu de ma fonction, voici ce que j'obtiens comme valeurs :

  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
126
127
128
129
130
131
132
133
134
135
136
118.45643845118
118.44117186163
118.42408910019
118.40352901006
118.38056613377
118.35505657189
118.32677999485
118.29536279668
118.26149081371
118.22472323491
118.18527233665
118.14316148738
118.0968799681
118.05063090804
117.99979346903
117.94717775575
117.89119488816
117.83278123613
117.77000691814
117.63945200258
117.57099118238
117.56393110987
117.53890404025
117.53028952895
117.52355658628
117.51702287828
117.51028532186
117.50339473103
117.49644317272
117.4245134716
117.34576866273
117.26629662336
117.18343809195
117.09715727281
117.00865636058
116.91703978602
116.82327665074
116.72487646557
116.62513231204
116.52454268447
116.41993018221
116.31183049271
116.20121109349
116.08582388974
115.97234487851
115.85015582794
115.72917055663
115.604479575
115.47964124534
115.35210035604
115.21935127337
115.08404287225
114.94520320028
114.80529083561
114.65891212697
114.51367850658
114.36436549228
114.21035551997
114.05900306305
113.89765865628
113.74421926918
113.41734504422
113.25050169049
113.23417010559
113.21698043696
113.15362475783
113.13700921983
113.12104589311
113.10585937125
113.09017834011
113.0744039719
112.90758675312
112.727008407
112.55217344609
112.36872385294
112.18705529366
111.99987772828
111.8001028431
111.61495570017
111.41990793641
111.22363037717
111.02303636798
110.820514574
110.61547498356
110.40288396556
110.19463503966
109.76350914489
109.54341509513
109.52044851783
109.4416669463
109.41655241607
109.39612977644
109.37695000456
109.35560355969
109.32729517671
109.09727176946
108.86757037222
108.63538232035
108.4026356046
108.16568328537
107.92618519634
107.68720718773
107.44350118184
107.19645886862
106.9469130415
106.69441691757
106.43671783043
106.18048805345
105.91838784027
105.65697163997
105.38959072577
105.12243470824
104.57335744055
104.2991315006
104.27075749525
104.17563471525
104.14370369891
104.11768853878
104.09238305869
104.06797774545
104.04354178318
104.01629785481
103.73624204779
103.44509655586
103.16003890734
102.87300826919
102.57918117079
102.27693654247
101.96545489692
101.67717130757
101.3752788848
101.06704707274
100.7568059811
100.44875215231
100.12960649246
99.813574167192

Et ça continue à descendre comme ça sauf que les valeurs sont de plus en plus espacées. Enfaite je pense que mes valeurs sont trop grandes et donc en les multipliant par $dt$ qui est inférieur à 0, je les réduisait. Mais du coup… Comment je suis sensé les réduire ? En multipliant par 0.05 j'obtiens un résultat qui ressemble à la situation avec $dt$ (pour te donner un ordre d'idée).

Ah je pense avoir compris. Ma seconde équation n'utilise seulement la position de $x$ pour déterminer la position de $y$ donc pas besoin de $dt$.

C'est ça.

Mais ce que je ne comprend pas, c'est que ça ne fonctionne pas sans.

Regarde bien ton calcul de $y$. Ce n'est toujours pas l'équation $y(x)$ que tu as marqué dans ton premier post (EDIT, pour rappel, j'ai même mis la bonne ligne de code dans un de mes précédents posts).

+0 -0

Regarde bien ton calcul de $y$. Ce n'est toujours pas l'équation $y(x)$ que tu as marqué dans ton premier post (EDIT, pour rappel, j'ai même mis la bonne ligne de code dans un de mes précédents posts).

adri1

Ouep j'ai remarqué, c'est le signe - séparant les deux termes de mon équation. Mais en le mettant, on dirait que ma balle fait 500 tonnes, j'obtiens un léger décalage sur les x en mettant ball.velocity.x = 1000 ce qui est énorme !

Ouep j'ai remarqué, c'est le signe - séparant les deux termes de mon équation.

C'est vraiment pas le problème (d'ailleurs, le signe - me semble tout à fait logique puisque de mémoire l'axe y est orienté vers le bas).

Tu n'es pas assez attentif, vraiment entre ça (ta formule) :

1
ball.position.y = ball.position.y - (-0.5 * game.constants.g * (ball.position.x/ball.velocity.x)^2 + (game.height - ball.position.start.y))

et ça (la mienne, qui reprend d'ailleurs les mêmes signes que dans la tienne) :

1
ball.position.y = 0.5 * game.constants.g * (ball.position.x/ball.velocity.x)^2 - (game.height - ball.position.start.y)

il n'y a pas une grosse différence qui te frappe ?

+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