To pytanie jest kolejnym pytaniem z mojego poprzedniego, dotyczącym wykrywania i rozwiązywania kolizji, które można znaleźć tutaj .
Jeśli nie chcesz czytać poprzedniego pytania, oto krótki opis działania mojego silnika fizyki:
Każda jednostka fizyczna jest przechowywana w klasie o nazwie SSSPBody.
Obsługiwane są tylko AABB.
Każde ciało SSSPBody jest przechowywane w klasie o nazwie SSSPWorld, która aktualizuje każde ciało i obsługuje grawitację.
Każda ramka, SSSPWorld aktualizuje każde ciało.
Każde zaktualizowane ciało szuka pobliskich obiektów w haszu przestrzennym, sprawdza, czy muszą wykryć kolizje z nimi. Jeśli tak, wywołują zdarzenie „kolizji” i sprawdzają, czy muszą rozwiązać z nimi kolizje. Jeśli tak, obliczają wektor penetracji i kierunkowe nakładanie się, a następnie zmieniają pozycję w celu rozwiązania penetracji.
Kiedy ciało zderza się z innym, przenosi prędkość na drugie, po prostu ustawiając prędkość ciała na własną.
Prędkość ciała jest ustawiona na 0, jeśli nie zmieniła pozycji od ostatniej klatki. Jeśli zderzy się również z ruchomym ciałem (takim jak winda lub ruchome platformy), oblicza różnicę ruchu windy, aby sprawdzić, czy ciało nie poruszyło się z ostatniej pozycji.
Ponadto ciało wywołuje zdarzenie „zmiażdżenia”, gdy wszystkie jego narożniki AABB nachodzą na coś w ramce.
To jest PEŁNY kod źródłowy mojej gry. Jest podzielony na trzy projekty. SFMLStart to prosta biblioteka obsługująca wprowadzanie danych, rysowanie i aktualizację encji. SFMLStartPhysics jest najważniejszy, w którym znajdują się klasy SSSPBody i SSSPWorld. PlatformerPhysicsTest to projekt gry, zawierający całą logikę gry.
I to jest „aktualizacja” metoda w klasie SSSPBody komentuje i uproszczonej. Możesz na to spojrzeć tylko wtedy, gdy nie masz ochoty patrzeć na cały projekt SFMLStartSimplePhysics. (A nawet jeśli to zrobisz, powinieneś jeszcze rzucić na to okiem, ponieważ jest to komentarz).
.Gif pokazuje dwa problemy.
- Jeśli ciała zostaną umieszczone w innej kolejności, wystąpią różne wyniki. Skrzynie po lewej są identyczne jak skrzynki po prawej stronie, umieszczone tylko w odwrotnej kolejności (w edytorze).
- Obie skrzynki powinny być napędzane w kierunku górnej części ekranu. W sytuacji po lewej skrzynie nie są napędzane. Po prawej stronie jest tylko jeden z nich. Obie sytuacje są niezamierzone.
Pierwszy problem: kolejność aktualizacji
Jest to dość proste do zrozumienia. W sytuacji po lewej, najwyższa skrzynia jest aktualizowana przed drugą. Nawet jeśli skrzynia na dole „przenosi” prędkość na drugą, musi poczekać na przejście następnej klatki. Ponieważ się nie poruszał, prędkość dolnej skrzyni jest ustawiona na 0.
Nie mam pojęcia, jak to naprawić. Wolałbym, żeby to rozwiązanie nie zależało od „sortowania” listy aktualizacji, ponieważ czuję, że robię coś złego w całym projekcie silnika fizyki.
Jak główne silniki fizyki (Box2D, Bullet, Chipmunk) radzą sobie z kolejnością aktualizacji?
Drugi problem: tylko jedna skrzynia jest napędzana w kierunku sufitu
Jeszcze nie rozumiem, dlaczego tak się dzieje. To, co robi „sprężyna”, ustawia prędkość ciała na -4000 i ponownie ustawia ją nad samą sprężyną. Nawet jeśli wyłączę kod zmiany położenia, problem nadal występuje.
Mój pomysł jest taki, że kiedy dolna skrzynia zderza się z górną skrzynią, jej prędkość jest ustawiona na 0. Nie jestem pewien, dlaczego tak się dzieje.
Pomimo szansy na wyglądanie jak ktoś, kto zrezygnuje z pierwszego problemu, zamieściłem cały kod źródłowy projektu powyżej. Nie mam niczego, co by to udowodniło, ale uwierzcie mi, starałem się to naprawić, ale po prostu nie mogłem znaleźć rozwiązania i nie mam wcześniejszego doświadczenia z fizyką i kolizjami. Próbowałem rozwiązać te dwa problemy od ponad tygodnia, a teraz jestem zdesperowany.
Nie sądzę, że mogę znaleźć rozwiązanie samodzielnie, bez usuwania wielu funkcji z gry (na przykład przenoszenia prędkości i sprężyn).
Bardzo dziękuję za czas poświęcony na przeczytanie tego pytania, a jeszcze bardziej, jeśli nawet spróbujesz znaleźć rozwiązanie lub sugestię.