Mouvement de projectile - Flèche

13

Dans un jeu 2D, je veux simplement dessiner la trajectoire d'une flèche en vol. Avec le code ci-dessous, la trajectoire (la parabole) semble droite, mais l'angle (ou la rotation) ou la flèche ne l'est pas.

float g = -9.8f;
float x = (launchVelocity * time);
float y = (launchVelocity * time) + (0.5f * g * (float)Math.Pow(time, 2));
float angle = (float)Math.Tanh(y / x);

Qu'est-ce que je rate? Merci.

Martin
la source
3
Une capture d'écran peut vous aider
doppelgreener

Réponses:

10

Arctanhvous donne la tangente de la courbe hyperbolique! Pour autant que je sache, votre parabole n'est pas une hyperbole.

Mais nous avons une bonne nouvelle: trouver la tangente pour votre parabole est plus facile. L'équation est

x = s · t => t = x / s; y = s · t + g / 2 · t² => y = x + g / 2 · x² / s²

Où est ton launchVelocity. Maintenant, la pente de votre flèche est:

∂y / ∂y = g / (2s²) · x + 1

Vous pouvez Arctanmaintenant l' utiliser en toute sécurité si vous le souhaitez.

Quelques informations supplémentaires sur la physique:

La trajectoire approximative que vous simulez s'applique au centre de masse de votre flèche. Lorsque vous dites «position» (x, y), vous parlez de la position du centre de gravité. Le centre de gravité d'une flèche est légèrement en avant à partir du milieu et vous devez en tenir compte si vous voulez dessiner la flèche.

Gardez à l'esprit que vous ne considérez pas le moment d'inertie de la flèche (qui peut varier beaucoup si vous tirez une baliste géante) et que vous ne considérez pas la dynamique des fluides de la flèche: le vol de la flèche d'arc ne suivra pas un chemin parabolique!

FxIII
la source
Merci Fxlll. Une idée où je pourrais obtenir les formules qui s'appliquent à la physique d'une flèche?
Martin
Je pense que vous voulez dire:! [& Part; y / & part; x = g / (2s & sup2;) & middot; x + 1] [2] mais en tout cas je pense que j'ai recommandé une meilleure approche ci-dessous. D'une part, vous n'avez pas expliqué la séparation des composants x et y, donc cela est codé en dur à un angle arbitraire de 45 degrés, avec launchVelocity n'étant pas vraiment launchVelocity, mais le composant à la fois en x et y
Dov
On peut facilement calculer les moments d'inertie. Ce sont deux pour les tiges, un pour la rotation autour de son centre de masse et l'autre pour la rotation autour de l'axe de la tige. Le principe de superposition s'applique aux moments d'inertie de sorte que la flèche peut être divisée en trois parties: plumes, corps et pointe.
FxIII
1
Le problème est que la seule impulsion est facile à calculer est celle due à la variation d'angle (vous pouvez voir que dériver deux fois une parabole ne reste qu'un terme constant). L'autre est causé par la rotation due à la plume arrière. Ici, les traînées de plumes et le frottement sont impliqués dans la conversion de l'énergie cinétique en rotation, ralentissant la flèche mais ajoutant un effet gyroscopique. Cela influence la trajectoire et est assez difficile à modéliser
FxIII
Quoi qu'il en soit, si vous pouvez relier l'élan à la vitesse avec une configuration de plumes, tout peut être calculé en profondeur, mais je ne suis pas sûr que vous puissiez avoir une forme fermée pour les équations du mouvement (c'est-à-dire que vous pouvez obtenir un algorithme d'intégration mais pas paramétrique équation).
FxIII
4

Vous voulez l'angle de la flèche à tout moment. Vous vous souvenez que pour calculer un angle, il y a une tangente. Mais voici où votre réflexion a commencé à mal tourner:

  1. Ce que vous voulez, c'est delta y / delta x, car la pente est le taux de variation (mentionné dans l'une des autres réponses). Notez que x est juste la position où vous vous trouvez à tout moment, pas dx.

Ok, donc si vous négligez le frottement de l'air, la vitesse x de la flèche est constante.

Tout d'abord, décomposez la vitesse en composantes x et y. Vous pourriez photographier à un angle de 45 degrés ou 60 degrés. Vous avez donc besoin de launchVelocity et d'un angle, ce n'est pas un scalaire.

Deuxièmement, calculez tout comme double et non flottant. Vous n'êtes pas suffisamment sophistiqué numériquement pour savoir quand une erreur d'arrondi ne vous tuera pas, alors n'essayez pas. Ce n'est pas un grand gain de temps en tout cas.

Troisièmement, n'utilisez pas Math.pow, c'est lent et pas aussi précis que de multiplier pour des puissances entières. Vous pouvez également gagner beaucoup de temps en utilisant le formulaire de Horner (voir ci-dessous)

final double DEG2RAD = Math.PI/180;
double ang = launchAngle * DEG2RAD;
double v0x = launchVelocity * cos(ang); // initial velocity in x
double v0y = launchVelocity * sin(ang); // initial velocity in y

double x = (v0x * time);
// double y = (v0y * time) + (0.5 * g * (float)Math.Pow(time, 2));
double y = (0.5 * g * time + v0y) * time

Si vous cherchez désespérément des performances, vous pouvez même précalculer 0,5 * g, mais le code ci-dessus vous mènera à 90% du chemin sans rien faire de trop fou. Benchmark faisant cela 10 millions de fois si vous le souhaitez, ce n'est certes pas beaucoup de temps, mais en pourcentage, c'est assez grand - les bibliothèques sont très lentes en Java

Donc, si vous vouliez l'angle auquel la flèche devrait aller, ce que vous voulez c'est

atan(dy/dx)

Et dans ce cas, cela fonctionnerait parce que dx est une constante. Mais en général, dx peut être nul, vous devez donc généralement utiliser:

atan2(dy, dx)

qui est une fonction spécialement conçue pour ce travail.

Mais comme je l'ai dit, les fonctions de bibliothèque en Java sont horriblement lentes, et dans ce cas, il y a une meilleure façon de le faire sans comme mentionné par @FxIII ci-dessus.

Si la vitesse horizontale est toujours v0x et la vitesse verticale est:

double vy = v0y - 0.5 * g * time;

alors votre delta est: vx, vy

Vous n'avez pas besoin de l'angle. Si vous vouliez dessiner une flèche, utilisez quelque chose nominalement comme:

tracé (x, y, x + vx, y + vy);

Je ne sais pas ce que vous dessinez, donc si vous avez besoin de l'angle pour le faire pivoter (comme vous utilisez JOGL), alors bien sûr, utilisez l'angle.

N'oubliez pas si vous utilisez opengl pour retourner l'angle en degrés, car ATAN2 renvoie des radians:

final double RAD2DEG = 180 / Math.PI;
double ang = Math.atan2(vy,vx); // don't forget, vy first!!!
double deg = ang * RAD2DEG;
Dov
la source
2

Tanh () ( tangente hyperbolique ) prend un angle comme paramètre, mais vous lui avez donné le rapport des côtés.

Ce que vous voulez vraiment, c'est utiliser l' arctangente hyperbolique , qui prend le rapport des côtés comme paramètre et renvoie l'angle. (La dénomination peut être "atanh", "atanh2", "arctanh", ou quelque chose de similaire; semble varier beaucoup entre les différentes bibliothèques mathématiques)

Trevor Powell
la source
Non, vous ne voulez rien d'hyperbolique
Dov
Gah, vous avez absolument raison. J'ai immédiatement compris l'erreur "utilisation de la trigonométrie de base" et j'ai raté que la fonction qu'il utilisait était complètement incorrecte pour le reste de son approche.
Trevor Powell
Tan () prend un angle. Atan prend un rapport côté triangle (sin / cos).
3Dave