Jak mogę wprowadzić grawitację? Nie dla konkretnego języka, tylko pseudokod ...
software-engineering
physics
Pizzirani Leonardo
źródło
źródło
Odpowiedzi:
Jak zauważyli inni w komentarzach, podstawowa metoda integracji Eulera opisana w odpowiedzi tenpn ma kilka problemów:
Nawet w przypadku zwykłego ruchu, takiego jak skoki balistyczne pod stałym ciężarem, wprowadza błąd systematyczny.
Błąd zależy od timepeptu, co oznacza, że zmiana timepeptu zmienia systemowe trajektorie obiektów, co może być zauważone przez graczy, jeśli gra używa zmiennej timepeptu. Nawet w przypadku gier o ustalonym czasie fizyki, zmiana czasu podczas programowania może znacząco wpłynąć na fizykę gry, na przykład na odległość, na jaką latać będzie obiekt wystrzelony z daną siłą, potencjalnie przekraczając wcześniej zaprojektowane poziomy.
Nie oszczędza energii, nawet jeśli podstawowa fizyka powinna. W szczególności obiekty, które powinny oscylować równomiernie (np. Wahadła, sprężyny, orbitujące planety itp.) Mogą stale gromadzić energię, dopóki cały system się nie rozpadnie.
Na szczęście nie jest trudno zastąpić integrację Eulera czymś, co jest prawie tak proste, ale nie ma żadnego z tych problemów - a konkretnie integratora symplektycznego drugiego rzędu, takiego jak integracja skoków lub ściśle związana metoda prędkości Verleta . W szczególności, gdy podstawowa integracja Eulera aktualizuje prędkość i położenie jako:
metoda prędkości Verlet robi to tak:
Jeśli masz wiele współdziałających obiektów, powinieneś zaktualizować wszystkie ich pozycje przed ponownym obliczeniem sił i zaktualizowaniem prędkości. Nowe przyspieszenie (a) można następnie zapisać i wykorzystać do aktualizacji pozycji (pozycji) przy następnym takcie czasowym, zmniejszając liczbę wywołań
force()
do jednego (na obiekt) na czas, tak jak w przypadku metody Eulera.Ponadto, jeśli przyspieszenie jest zwykle stałe (podobnie jak grawitacja podczas skoków balistycznych), możemy uprościć powyższe, aby:
gdzie dodatkowy termin pogrubiony jest jedyną zmianą w porównaniu do podstawowej integracji Eulera.
W porównaniu z integracją Eulera metody Verlet prędkości i leapfrog mają kilka fajnych właściwości:
W przypadku stałego przyspieszenia dają dokładne wyniki (w każdym razie do błędów zaokrąglenia zmiennoprzecinkowego), co oznacza, że trajektorie skoku balistycznego pozostają takie same, nawet jeśli zmiana czasu jest zmieniona.
Są to integratory drugiego rzędu, co oznacza, że nawet przy różnym przyspieszeniu średni błąd integracji jest tylko proporcjonalny do kwadratu pomiaru czasu. Może to pozwolić na dłuższe kroki bez utraty dokładności.
Są symplektyczni , co oznacza, że oszczędzają energię, jeśli robią to podstawy fizyki (przynajmniej tak długo, jak czas jest stały). W szczególności oznacza to, że nie dostaniesz takich rzeczy, jak planety spontanicznie wylatujące z ich orbit, lub obiekty połączone ze sobą sprężynami, które stopniowo będą się coraz bardziej chwiejne, aż cała rzecz wybuchnie.
Jednak metoda prędkości Verlet / leapfrog jest prawie tak prosta i szybka jak podstawowa integracja Eulera, a na pewno znacznie prostsza niż alternatywy, takie jak integracja Runge-Kutta czwartego rzędu (która, ogólnie rzecz biorąc, bardzo fajny integrator, nie ma własności symplektycznej i wymaga czterech ocen w
force()
funkcji dla każdego kroku czasowego). Dlatego zdecydowanie polecam je wszystkim, którzy piszą dowolny kod fizyki gry, nawet jeśli jest to tak proste, jak przeskakiwanie z jednej platformy na drugą.Edycja: Podczas gdy formalne wyprowadzenie metody Verleta prędkości jest ważne tylko wtedy, gdy siły są niezależne od prędkości, w praktyce można z niej dobrze korzystać nawet przy siłach zależnych od prędkości, takich jak opór płynu . Aby uzyskać najlepsze wyniki, należy użyć początkowej wartości przyspieszenia, aby oszacować nową prędkość dla drugiego wezwania do
force()
:Nie jestem pewien, czy ten konkretny wariant metody Verleta prędkości ma konkretną nazwę, ale przetestowałem go i wydaje się, że działa bardzo dobrze. Nie jest tak dokładny jak Runge-Kutta rzędu Foutha (jak można by oczekiwać po metodzie drugiego rzędu), ale jest znacznie lepszy niż Euler lub Verve naiwna prędkość bez pośredniej oceny prędkości i nadal zachowuje symplektyczną właściwość normalnej vellet Verlet dla konserwatywnych, niezależnych od prędkości sił.
Edycja 2: Bardzo podobny algorytm został opisany np. Przez Groota i Warrena ( J. Chem. Phys. 1997) , chociaż wydaje się, że czytając między wierszami, poświęcili oni pewną dokładność dla dodatkowej prędkości, zapisując
newAcceleration
wartość obliczoną przy użyciu oszacowanej prędkości i ponowne użycie go jakoacceleration
następnego kroku czasu. Wprowadzają również parametr 0 ≤ λ ≤ 1, który jest mnożonyacceleration
w początkowej estymacji prędkości; z jakiegoś powodu zalecają λ = 0,5, mimo że wszystkie moje testy sugerują, że λ= 1 (co jest efektywnie tym, czego używam powyżej) działa równie dobrze lub lepiej, z ponownym użyciem przyspieszenia lub bez niego. Może ma to coś wspólnego z faktem, że ich siły obejmują stochastyczny komponent ruchu Browna.źródło
force(time, position, velocity)
mojej powyższej odpowiedzi jest tylko skrótem dla „siły działającej na przedmiot przyposition
poruszaniu sięvelocity
otime
”. Zazwyczaj siła zależałaby od takich rzeczy, jak to, czy obiekt spada swobodnie, czy siedzi na twardej powierzchni, czy inne pobliskie obiekty wywierają na niego siłę, jak szybko porusza się po powierzchni (tarcie) i / lub przez ciecz lub gaz (drag) itp.Zrób każdą pętlę aktualizacji swojej gry:
Na przykład w platformówce po skoku grawitacja byłaby włączona (kolizja poniżej informuje, czy grunt znajduje się tuż pod tobą), a po uderzeniu w ziemię byłaby wyłączona.
Oprócz tego, aby wdrożyć skoki, wykonaj następujące czynności:
I oczywiście, w pętli aktualizacji musisz również zaktualizować swoją pozycję:
źródło
Właściwa integracja fizyki newtonowskiej niezależna od częstotliwości odświeżania:
Dostosuj grawitację Stała, ruch Stała i masowa Stała, aż poczuje się dobrze. Jest to intuicyjna rzecz i może zająć trochę czasu, aby poczuć się świetnie.
Łatwo jest rozszerzyć wektor sił, aby dodać nową rozgrywkę - na przykład dodać siłę od jakiejkolwiek pobliskiej eksplozji lub w kierunku czarnych dziur.
* edycja: wyniki te z czasem będą błędne, ale mogą być „wystarczająco dobre” dla twojej wierności lub umiejętności. Zobacz ten link http://lol.zoy.org/blog/2011/12/14/understanding-motion-in-games, aby uzyskać więcej informacji.
źródło
position += velocity * timestep
powyższyposition += (velocity - acceleration * timestep / 2) * timestep
(gdzievelocity - acceleration * timestep / 2
jest po prostu średnia ze starych i nowych prędkości). W szczególności ten integrator daje dokładne wyniki, jeśli przyspieszenie jest stałe, jak zwykle w przypadku grawitacji. Aby uzyskać lepszą dokładność przy różnym przyspieszeniu, możesz dodać podobną korektę do aktualizacji prędkości, aby uzyskać integrację prędkości Verlet .Jeśli chcesz wprowadzić grawitację na nieco większą skalę, możesz użyć tego rodzaju obliczeń dla każdej pętli:
W przypadku jeszcze większych (galaktycznych) skal sama grawitacja nie wystarczy, aby stworzyć „prawdziwy” ruch. Interakcja układów gwiezdnych jest w znacznym i bardzo widocznym stopniu podyktowana równaniami Naviera-Stokesa dla dynamiki płynów, a ty będziesz musiał pamiętać o skończonej prędkości światła - a więc i grawitacji - również.
źródło
Kod dostarczony przez Ilmari Karonen jest prawie poprawny, ale jest niewielka usterka. Rzeczywiście obliczasz przyspieszenie 2 razy na tik, nie jest to zgodne z równaniami podręcznika.
Następujący mod jest poprawny:
Twoje zdrowie'
źródło
Program odpowiadający Pecant zignorował czas klatki, a to od czasu do czasu zmienia twoje zachowanie fizyczne.
Jeśli zamierzasz stworzyć bardzo prostą grę, możesz stworzyć swój własny silnik fizyki - przypisać masę i wszelkiego rodzaju parametry fizyki do każdego poruszającego się obiektu, a także wykonać wykrywanie kolizji, a następnie zaktualizować ich pozycję i prędkość dla każdej klatki. Aby przyspieszyć ten postęp, musisz uprościć siatkę kolizyjną, zmniejszyć liczbę wezwań do wykrywania kolizji itp. W większości przypadków jest to uciążliwe.
Lepiej jest używać silnika fizyki, takiego jak physix, ODE i kula. Każdy z nich będzie dla Ciebie stabilny i wystarczająco wydajny.
http://www.nvidia.com/object/physx_new.html
http://bulletphysics.org/wordpress/
źródło