Ruch pocisku - strzałka

13

W grze 2D po prostu chcę narysować trajektorię strzały w locie. Przy poniższym kodzie trajektoria (parabola) wygląda dobrze, ale kąt (lub obrót) lub strzałka nie.

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

czego mi brakuje? Dzięki.

Jaskółka oknówka
źródło
3
Zrzut ekranu może pomóc
doppelgreener

Odpowiedzi:

10

Arctanhdaje tangens dla krzywej hiperbolicznej! O ile wiem, twoja parabola nie jest hiperbolą.

Ale mamy dobre wieści: łatwiej jest znaleźć styczną do swojej paraboli. Równanie to

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

Gdzie jest twoje launchVelocity. Teraz nachylenie twojej strzałki to:

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

Możesz Arctanteraz bezpiecznie korzystać, jeśli chcesz.

Kilka dodatkowych informacji o fizyce:

Przybliżona trajektoria, którą symulujesz, odnosi się do środka masy twojej strzałki. Kiedy mówisz „pozycja” (x, y), mówisz o pozycji środka masy. Środek masy strzały jest lekko do przodu od punktu środkowego i należy wziąć to pod uwagę, jeśli zamierzasz narysować strzałkę.

Pamiętaj, że nie bierzesz pod uwagę bezwładności pędu strzały (która może się znacznie różnić, jeśli strzelasz olbrzymią balistą) i nie bierzesz pod uwagę płynności strzały: lot strzały łuku nie podąży paraboliczną ścieżką!

FxIII
źródło
Dziękuję Fxlll. Masz pomysł, gdzie mogę uzyskać formuły odnoszące się do fizyki strzały?
Martin
Myślę, że masz na myśli:! [& Part; y / & part; x = g / (2s & sup2;) & middot; x + 1] [2], ale w każdym razie myślę, że zaleciłem lepsze podejście poniżej. Po pierwsze, nie wyjaśniłeś, jak oddzielić komponenty xiy, więc jest to zakodowane na stałe pod dowolnym kątem 45 stopni, przy czym launchVelocity nie jest tak naprawdę launchVelocity, ale komponent zarówno x, jak i y
Dow
Momenty bezwładności można łatwo obliczyć. Są to dwa dla prętów, jeden dla obrotu wokół jego środka masy, a drugi dla obrotu wokół osi pręta. Zasada superpozycji dotyczy momentów bezwładności, dzięki czemu strzałkę można podzielić na trzy części: pióra, ciało i czubek.
FxIII
1
Problem polega na tym, że jedynym momentem, który łatwo jest obliczyć, jest ten, który wynika ze zmiany kąta (widać, że wyprowadzenie podwójnej paraboli pozostaje tylko stałym terminem). Drugi jest spowodowany wirowaniem z powodu tylnego pióra. W grę wchodzą przeciągnięcia piór i tarcie, które przekształcają energię kinetyczną w spinning, spowalniając strzałę, ale dodając efekt żyroskopowy. Wpływa to na trajektorię i jest dość trudne do modelowania
FxIII,
W każdym razie, jeśli możesz powiązać pęd z prędkością przy danej konfiguracji piór, wszystko można obliczyć dokładną integrację, ale nie jestem pewien, czy możesz mieć zamkniętą postać dla równań ruchu (tj. Możesz uzyskać algorytm integracji, ale nie parametryczny równanie).
FxIII
4

Chcesz kąt strzałki w dowolnym momencie. Pamiętasz, że aby obliczyć kąt, istnieje styczna. Ale tutaj twoje myślenie zaczęło się mylić:

  1. To, czego chcesz, to delta y / delta x, ponieważ nachylenie to szybkość zmian (wspomniana w jednej z pozostałych odpowiedzi). Zauważ, że x to tylko pozycja, w której jesteś w dowolnym momencie, a nie dx.

Ok, więc jeśli zaniedbacie tarcie powietrzne, wówczas prędkość x strzałki jest stała.

Najpierw rozłóż prędkość na składowe xiy. Możesz strzelać pod kątem 45 stopni lub 60 stopni. Potrzebujesz więc launchVelocity i kąta, to nie jest skalar.

Po drugie, oblicz wszystko jako podwójne, a nie zmiennoprzecinkowe. Nie jesteś wystarczająco zaawansowany numerycznie, aby wiedzieć, kiedy błąd zaokrągleń cię nie zabije, więc nie próbuj. W każdym razie nie jest to świetna oszczędność czasu.

Po trzecie, nie używaj Math.pow, jest powolny i nie tak dokładny, jak mnożenie potęg liczb całkowitych. Możesz także zaoszczędzić dużo czasu, korzystając z formularza Hornera (patrz poniżej)

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

Jeśli zależy ci na wydajności, możesz nawet wstępnie obliczyć 0,5 * g, ale powyższy kod zabierze Cię tam w 90%, nie robiąc nic zbyt szalonego. Benchmark, robiąc to 10 milionów razy, jeśli chcesz, to wprawdzie nie jest to dużo czasu, ale pod względem procentowym jest dość duży - biblioteki są bardzo wolne w Javie

Tak więc, jeśli chcesz kąt, pod którym powinna iść strzała, to czego chcesz

atan(dy/dx)

W tym przypadku zadziałałoby, ponieważ dx jest stałą. Ale ogólnie dx może wynosić zero, więc zwykle chcesz użyć:

atan2(dy, dx)

która jest funkcją zaprojektowaną specjalnie do tego zadania.

Ale, jak powiedziałem, funkcje biblioteczne w Javie są strasznie powolne, i w tym przypadku jest lepszy sposób na zrobienie tego bez aluzji @FxIII powyżej.

Jeśli prędkość pozioma wynosi zawsze v0x, a prędkość pionowa wynosi:

double vy = v0y - 0.5 * g * time;

wtedy twoja delta to: vx, vy

Nie potrzebujesz kąta. Jeśli chcesz narysować strzałkę, użyj czegoś nominalnie takiego jak:

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

Nie wiem, co rysujesz, więc jeśli potrzebujesz kąta, aby go obrócić (tak jak używasz JOGL), to na pewno użyj tego kąta.

Nie zapomnij, jeśli używasz opengl do zmiany kąta z powrotem na stopnie, ponieważ ATAN2 zwraca radiany:

final double RAD2DEG = 180 / Math.PI;
double ang = Math.atan2(vy,vx); // don't forget, vy first!!!
double deg = ang * RAD2DEG;
Dow
źródło
2

Tanh () ( tangens hiperboliczny ) przyjmuje jako parametr kąt, ale podałeś mu stosunek boków.

To, czego naprawdę chcesz, to użyć arcus tangensa hiperbolicznego , który przyjmuje parametr boków jako parametr i zwraca kąt. (Nazewnictwo może nazywać się „atanh”, „atanh2”, „arctanh” lub coś podobnego; wydaje się, że różni się w zależności od różnych bibliotek matematycznych)

Trevor Powell
źródło
Nie, nie chcesz niczego hiperbolicznego
Dow
Gah, masz absolutną rację. Natychmiast zauważyłem błąd „użycia podstawowej trygonometrii” i nie zauważyłem, że funkcja, której używał, była całkowicie niepoprawna przez resztę jego podejścia.
Trevor Powell,
Tan () przyjmuje kąt. Atan przyjmuje stosunek boków trójkąta (sin / cos).
3Dave