Proiettile Motion - Freccia


13

In un gioco 2D, voglio semplicemente disegnare la traiettoria di una freccia in volo. Con il codice in basso, la traiettoria (la parabola) sembra corretta, ma l'angolo (o la rotazione) o la freccia no.

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);

Cosa mi sto perdendo? Grazie.


3
Uno screenshot può essere d'aiuto
doppelgreener,

Risposte:


10

Arctanhti dà la tangente per la curva iperbolica! Per quanto ne so, la tua parabola non è un'iperbole.

Ma abbiamo buone notizie: trovare la tangente per la tua parabola è più facile. L'equazione è

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

Dov'è tuo launchVelocity. Ora la pendenza della tua freccia è:

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

ArctanSe lo desideri, puoi usare la sicurezza ora.

Alcune informazioni aggiuntive sulla fisica:

La traiettoria approssimativa che stai simulando si applica al centro di massa della tua freccia. Quando dici "posizione" (x, y) stai parlando del centro della posizione della massa. Il centro di massa di una freccia è leggermente in avanti rispetto al punto medio e dovresti tenerne conto se vuoi disegnare la freccia.

Tieni presente che non stai considerando il momento inerziale della freccia (che può variare molto se stai sparando un balista gigante) e non stai prendendo in considerazione la fluidodinamica della freccia: il volo della freccia di prua non seguirà un percorso parabolico!


Grazie Fxlll. Qualche idea su dove potrei ottenere le formule che si applicano alla fisica di una freccia?
Martin,

Penso che intendi:! [& Part; y / & part; x = g / (2s & sup2;) & middot; x + 1] [2] ma in ogni caso penso di aver raccomandato un approccio migliore di seguito. Per prima cosa, non hai spiegato come separare i componenti xey, quindi questo è hardcoded in un angolo arbitrario di 45 gradi, con launchVelocity non essendo veramente launchVelocity, ma il componente in entrambi xey
Dov

Si possono calcolare facilmente i momenti di inerzia. Questi sono due per le aste, uno per la rotazione attorno al suo centro di massa e l'altro per la rotazione attorno all'asse dell'asta. Il principio di sovrapposizione si applica ai momenti di inerzia, quindi la freccia può essere divisa in tre parti: piume, corpo e punta.
FxIII,

1
Il problema è che l'unico momento che è facile da calcolare è quello dovuto alla variazione dell'angolo (puoi vedere che derivare due volte una parabola rimane solo un termine costante). L'altro è causato dalla rotazione dovuta alla piuma posteriore. Qui sono coinvolti trascinamenti di piume e attrito, entrambi convertendo l'energia cinetica in rotazione, rallentando la freccia ma aggiungendo un effetto giroscopico. Ciò influenza la traiettoria ed è piuttosto difficile da modellare
FxIII

Ad ogni modo, se riesci a mettere in relazione lo slancio con la velocità data da una configurazione sfumata, tutto può essere calcolato con una completa integrazione ma non sono sicuro di poter avere una forma chiusa per le equazioni del movimento (cioè puoi ottenere un algoritmo di integrazione ma non un parametro equazione).
FxIII,

4

Vuoi l'angolo della freccia in qualsiasi momento. Ti sei ricordato che per calcolare un angolo c'è una tangente. Ma qui è dove il tuo pensiero ha iniziato a sbagliare:

  1. Quello che vuoi è delta y / delta x, perché la pendenza è la velocità di variazione (menzionata in una delle altre risposte). Nota che x è solo la posizione in cui ti trovi in ​​qualsiasi momento, non dx.

Ok, quindi se trascuri l'attrito dell'aria, la velocità x della freccia è una costante.

Innanzitutto, decomporre la velocità in componenti xey. Potresti sparare con un angolo di 45 gradi o 60 gradi. Quindi hai bisogno di launchVelocity e un angolo, non è uno scalare.

Secondo, calcola tutto come doppio, non float. Non sei abbastanza numericamente sofisticato da sapere quando l'errore di arrotondamento non ti ucciderà, quindi non provare. Non è comunque un grande risparmio di tempo.

Terzo, non usare Math.pow, è lento e non accurato come moltiplicarsi per i poteri interi. Inoltre puoi risparmiare molto tempo usando il modulo di Horner (vedi sotto)

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

Se sei alla disperata ricerca di prestazioni, puoi anche pre-calcolare 0,5 * g, ma il codice sopra ti porterà al 90% del percorso senza fare nulla di troppo folle. Se lo desideri, fai questo benchmark 10 milioni di volte, è vero che non è un tempo enorme, ma in termini percentuali è piuttosto grande - le librerie sono molto lente in Java

Quindi, se volevi l'angolo in cui la freccia dovrebbe andare, quello che vuoi è

atan(dy/dx)

E in questo caso, funzionerebbe perché dx è una costante. Ma in generale, dx può essere zero, quindi di solito si desidera utilizzare:

atan2(dy, dx)

che è una funzione appositamente progettata per questo lavoro.

Ma come ho detto, le funzioni di libreria in Java sono tremendamente lente, e in questo caso c'è un modo migliore di farlo senza come accennato da @FxIII sopra.

Se la velocità orizzontale è sempre v0x e la velocità verticale è:

double vy = v0y - 0.5 * g * time;

allora il tuo delta è: vx, vy

Non hai bisogno dell'angolo. Se vuoi disegnare una freccia, usa qualcosa di nominalmente come:

trama (x, y, x + vx, y + vy);

Non so cosa stai disegnando, quindi se hai bisogno dell'angolo per ruotarlo (come se stessi usando JOGL), allora sicuramente usa l'angolo.

Non dimenticare se stai usando Opengl per riportare l'angolo in gradi, perché ATAN2 restituisce radianti:

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

2

Tanh () ( tangente iperbolica ) prende un angolo come parametro, ma gli hai dato il rapporto tra i lati.

Quello che vuoi davvero è usare l' arctangente iperbolico , che prende il rapporto dei lati come parametro e restituisce l'angolo. (Il nome su questo può essere "atanh", "atanh2", "arctanh" o qualcos'altro simile; sembra variare molto tra le diverse librerie matematiche)


No, non vuoi nulla di iperbolico
Dov,

Gah, hai assolutamente ragione. Ho subito compreso l'errore "utilizzo della trigonometria di base" e mi sono perso che la funzione che stava usando era completamente errata per il resto del suo approccio.
Trevor Powell,

Tan () prende un angolo. Atan prende un rapporto lato triangolo (sin / cos).
3Daveva il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.