Geschossbewegung - Pfeil

13

In einem 2D-Spiel möchte ich einfach die Flugbahn eines Pfeils im Flug zeichnen. Mit dem folgenden Code sieht die Flugbahn (die Parabel) richtig aus, nicht aber der Winkel (oder die Drehung) oder der Pfeil.

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

Was vermisse ich? Vielen Dank.

Martin
quelle
3
Ein Screenshot könnte helfen
doppelgreener 20.06.11

Antworten:

10

Arctanhgibt dir den tangens für die hyperbolische kurve! Soweit ich weiß, ist Ihre Parabel keine Hyperbel.

Aber wir haben eine gute Nachricht: Es ist einfacher, die Tangente für Ihre Parabel zu finden. Die Gleichung lautet

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

Wo ist dein launchVelocity. Jetzt ist die Steigung Ihres Pfeils:

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

Sie können Arctanjetzt die Sicherheit verwenden, wenn Sie möchten.

Einige zusätzliche Informationen zur Physik:

Die ungefähre Flugbahn, die Sie simulieren, gilt für den Schwerpunkt Ihres Pfeils. Wenn Sie "Position" (x, y) sagen, sprechen Sie von der Position des Massenschwerpunkts. Der Massenmittelpunkt eines Pfeils ist vom Mittelpunkt aus leicht nach vorne gerichtet, und Sie sollten dies berücksichtigen, wenn Sie den Pfeil zeichnen möchten.

Denken Sie daran, dass Sie das Trägheitsmoment des Pfeils (das beim Abfeuern eines riesigen Ballistas sehr unterschiedlich sein kann) und die Fluiddynamik des Pfeils nicht berücksichtigen: Der Bogen-Pfeil-Flug folgt keinem parabolischen Pfad!

FxIII
quelle
Vielen Dank, Fxlll. Irgendeine Idee, wo ich die Formeln bekommen könnte, die auf die Physik eines Pfeils zutreffen?
Martin
Ich denke, Sie meinen:! [& Part; y / & part; x = g / (2s & sup2;) & middot; x + 1] [2], aber auf jeden Fall empfehle ich einen besseren Ansatz. Zum einen haben Sie das Trennen der x- und y-Komponenten nicht erklärt. Daher ist dies in einem beliebigen 45-Grad-Winkel fest codiert, wobei launchVelocity nicht wirklich launchVelocity ist, sondern die Komponente in x und y
Dov
Man kann die Trägheitsmomente leicht berechnen. Dies sind zwei für Stäbe, einer für die Drehung um den Schwerpunkt und der andere für die Drehung um die Stabachse. Das Überlagerungsprinzip gilt für Trägheitsmomente, sodass der Pfeil in drei Teile geteilt werden kann: Federn, Körper und Spitze.
FxIII
1
Das Problem besteht darin, dass der einzige Impuls, der leicht zu berechnen ist, derjenige ist, der auf die Winkelvariation zurückzuführen ist (Sie können sehen, dass bei zweimaliger Ableitung einer Parabel nur ein konstanter Term übrig bleibt). Der andere wird durch das Durchdrehen der Rückenfeder verursacht. Hier geht es um Federn und Reibung, die kinetische Energie in Rotation umwandeln, den Pfeil verlangsamen, aber den Kreiseleffekt verstärken. Dies beeinflusst die Flugbahn und ist ziemlich schwierig zu modellieren
FxIII 20.06.11
Wie auch immer, wenn Sie den Impuls mit der Geschwindigkeit bei einer Federkonfiguration in Beziehung setzen können, kann alles durch Integration berechnet werden, aber ich bin nicht sicher, ob Sie eine geschlossene Form für die Bewegungsgleichungen haben können (dh Sie können einen Integrationsalgorithmus erhalten, aber keinen parametrischen Gleichung).
FxIII
4

Sie möchten den Winkel des Pfeils zu jedem Zeitpunkt. Sie haben sich daran erinnert, dass es zum Berechnen eines Winkels eine Tangente gibt. Aber hier begann Ihr Denken schief zu gehen:

  1. Was Sie wollen, ist Delta y / Delta x, weil die Steigung die Änderungsrate ist (in einer der anderen Antworten erwähnt). Beachten Sie, dass x nur die Position ist, an der Sie sich zu einem beliebigen Zeitpunkt befinden, nicht dx.

Wenn Sie also die Luftreibung vernachlässigen, ist die x-Geschwindigkeit des Pfeils eine Konstante.

Zerlegen Sie zunächst die Geschwindigkeit in x- und y-Komponenten. Sie könnten in einem Winkel von 45 Grad oder 60 Grad fotografieren. Sie brauchen also launchVelocity und einen Winkel, es ist kein Skalar.

Zweitens: Berechnen Sie alles als double, nicht als float. Sie sind nicht numerisch ausgereift genug, um zu wissen, wann ein Abrundungsfehler Sie nicht umbringt. Versuchen Sie es also nicht. Es ist auf keinen Fall eine große Zeitersparnis.

Drittens, verwenden Sie Math.pow nicht, es ist langsam und nicht so genau wie das Multiplizieren nach ganzzahligen Potenzen. Sie können auch viel Zeit sparen, indem Sie das Horner-Formular verwenden (siehe unten).

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

Wenn Sie verzweifelt nach Leistung streben, können Sie sogar 0,5 * g vorberechnen, aber der obige Code bringt Sie zu 90% dorthin, ohne etwas zu Verrücktes zu tun. Wenn Sie das 10 Millionen Mal machen, ist es zwar nicht sehr viel Zeit, aber prozentual gesehen ist es ziemlich groß - Bibliotheken sind in Java sehr langsam

Wenn Sie also den Winkel möchten, in dem der Pfeil verlaufen soll, ist das, was Sie möchten

atan(dy/dx)

Und in diesem Fall würde das funktionieren, weil dx eine Konstante ist. Im Allgemeinen kann dx aber auch Null sein, weshalb Sie normalerweise Folgendes verwenden möchten:

atan2(dy, dx)

Diese Funktion wurde speziell für diesen Job entwickelt.

Aber wie gesagt, Bibliotheksfunktionen in Java sind schrecklich langsam, und in diesem Fall gibt es eine bessere Möglichkeit, ohne @FxIII darauf hinzuweisen.

Wenn die horizontale Geschwindigkeit immer v0x ist und die vertikale Geschwindigkeit ist:

double vy = v0y - 0.5 * g * time;

dann ist dein Delta: vx, vy

Du brauchst den Winkel nicht. Wenn Sie einen Pfeil zeichnen möchten, verwenden Sie nominell Folgendes:

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

Ich weiß nicht, was Sie zeichnen. Wenn Sie also den Winkel zum Drehen benötigen (wie bei JOGL), verwenden Sie diesen Winkel.

Vergessen Sie nicht, wenn Sie opengl verwenden, um den Winkel wieder in Grad umzuwandeln, da ATAN2 Radiant zurückgibt:

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

Tanh () (hyperbolischer Tangens ) nimmt einen Winkel als Parameter, aber Sie haben das Verhältnis der Seiten angegeben.

Was Sie wirklich wollen, ist die Verwendung des hyperbolischen Arkustangens , der das Seitenverhältnis als Parameter verwendet und den Winkel zurückgibt. (Die Benennung kann "atanh", "atanh2", "arctanh" oder etwas ähnliches sein; scheint zwischen den verschiedenen Mathematikbibliotheken sehr zu variieren.)

Trevor Powell
quelle
Nein, Sie wollen nichts Hyperbolisches
Dov
Gah, du hast absolut recht. Ich bemerkte sofort den Fehler "Verwendung der grundlegenden Trigonometrie" und verpasste, dass die von ihm verwendete Funktion für den Rest seines Ansatzes völlig inkorrekt war.
Trevor Powell
Tan () nimmt einen Winkel ein. Atan nimmt ein Dreieckseitenverhältnis (sin / cos) an.
3Dave