Jestem tak matematyczny, że boli, ale dla niektórych z was to powinno być bułka z masłem. Chcę przesuwać obiekt wokół drugiego wzdłuż jego wieku lub obwodu po prostej, okrągłej ścieżce. W tej chwili mój algorytm gry wie, jak poruszać się i ustawiać duszka tuż przy krawędzi przeszkody, a teraz czeka na ruch następnego punktu w zależności od różnych warunków.
Problem matematyczny polega więc na tym, jak uzyskać pozycje (aX, aY) i (bX, bY) , gdy znam środek (cX, cY), pozycję obiektu (oX, oY) i odległość wymaganą do przesunięcia (d)
java
mathematics
Lumis
źródło
źródło
d
odległość jest liniowa czy jest to łuk?Odpowiedzi:
( CAVEAT: Używam tutaj dwóch aproksymacji: pierwsza przyjmuje d jako długość łuku, a druga przyjmuje ją jako długość ortogonalną. Oba te aproksymacje powinny być dobre dla stosunkowo małych wartości d, ale nie spełniają dokładne pytanie wyjaśnione w komentarzach).
Na szczęście matematyka na ten temat jest stosunkowo prosta. Przede wszystkim możemy znaleźć wektor względny od naszej pozycji środkowej do naszej aktualnej pozycji:
Po uzyskaniu tego wektora względnego możemy poznać promień okręgu, nad którym pracujemy, znajdując jego długość:
Co więcej, z naszego wektora względnego możemy znaleźć dokładny kąt, w którym linia od cX do oX ma:
Teraz sprawy stają się trochę trudniejsze. Przede wszystkim zrozum, że obwód koła - to znaczy „długość łuku” łuku o miary kątowej 2π - wynosi 2πr. Zasadniczo długość łuku łuku o wymiarze kątowym θ wzdłuż okręgu o promieniu r wynosi tylko θr. Gdybyśmy użyli litery d na twoim diagramie jako długości łuku, a ponieważ znamy promień, możemy znaleźć zmianę w theta, aby doprowadzić nas do nowej pozycji, po prostu dzieląc:
W przypadku, gdy d musi być odległością liniową, rzeczy są nieco bardziej skomplikowane, ale na szczęście niewiele. Tam, d jest jedną stroną trójkąta izoceles, którego pozostałe dwa boki są promieniem koła (odpowiednio od cX / cY do oX / oY i aX / aY), a podzielenie tego trójkąta izocelowego daje nam dwa trójkąty prawe, z których każdy ma d / 2 jako jedną stronę i promień jako przeciwprostokątną; oznacza to, że sinus połowy naszego kąta wynosi (d / 2) / promień, a zatem pełny kąt jest tylko dwa razy większy:
Zauważ, że jeśli wziąłeś asin z tej formuły i anulowałeś 2s, byłoby to takie samo jak w ostatnim wzorze; jest to to samo, co stwierdzenie, że sin (x) wynosi w przybliżeniu x dla małych wartości x, co jest przydatnym przybliżeniem do poznania.
Teraz możemy znaleźć nowy kąt, po prostu dodając lub odejmując:
Po uzyskaniu nowego kąta możemy użyć podstawowego wyzwalacza, aby znaleźć nasz zaktualizowany wektor względny:
a z naszej pozycji środkowej i naszego wektora względnego możemy (w końcu) znaleźć punkt docelowy:
Teraz, mając to wszystko na uwadze, należy pamiętać o kilku dużych zastrzeżeniach. Po pierwsze, zauważysz, że matematyka jest w większości zmiennoprzecinkowa i faktycznie musi być; próba użycia tej metody do aktualizacji w pętli i zaokrąglania z powrotem do wartości całkowitych na każdym kroku może zrobić wszystko, od sprawienia, że koło się nie zamyka (spirala do wewnątrz lub na zewnątrz za każdym razem, gdy okrążasz pętlę), po to, aby nie zacząć od pierwszego miejsce! (Jeśli twoje d jest zbyt małe, możesz odkryć, że zaokrąglone wersje aX / aY lub bX / bY są dokładnie tam, gdzie była twoja pozycja początkowa oX / oY.) Po drugie, jest to bardzo drogie, szczególnie za to, co próbuje zrobić; ogólnie, jeśli wiesz, że twoja postać będzie poruszać się po łuku kołowym, powinieneś zaplanować cały łuk z wyprzedzeniem, a niezaznaczaj go od ramki do ramki w ten sposób, ponieważ wiele z najdroższych obliczeń tutaj można załadować z przodu, aby obniżyć koszty. Innym dobrym sposobem na obniżenie kosztów, jeśli naprawdę chcesz aktualizować stopniowo w ten sposób, jest nie używanie triggera; jeśli d jest małe i nie potrzebujesz go dokładnie, ale po prostu bardzo blisko, możesz zrobić „lewę”, dodając wektor długości d do oX / oY, prostopadły do wektora w kierunku środka (zwróć uwagę, że a wektor ortogonalny do (dX, dY) jest podawany przez (-dY, dX)), a następnie zmniejszony do odpowiedniej długości. Nie będę wyjaśniać tego kodu krok po kroku, ale mam nadzieję, że będzie miał sens, biorąc pod uwagę to, co do tej pory widziałeś. Zauważ, że „zmniejszamy” nowy wektor delta domyślnie w ostatnim kroku,
źródło
Utwórz trójkąt, korzystając z dwóch boków, które już masz (jeden bok to „c” na „o”, drugi to „o” na „a”), a trzeci bok to „a” na „c”. Nie wiesz jeszcze, gdzie jest „a”, po prostu wyobraź sobie, że jest na razie sens. Będziesz potrzebować trygonometrii, aby obliczyć kąt kąta przeciwny do boku „d”. Masz długość boków c <-> o ic <-> a, ponieważ oba mają promień okręgu.
Teraz, gdy masz już długość trzech boków tego trójkąta, którego jeszcze nie widzisz, możesz określić kąt, który jest przeciwny do boku „d” trójkąta. Oto formuła SSS (side-side-side), jeśli potrzebujesz: http://www.teacherschoice.com.au/maths_library/trigonometry/solve_trig_sss.htm
Korzystając ze wzoru SSS masz kąt (który nazwiemy „j”), który jest przeciwny do boku „d”. Teraz możemy obliczyć (aX, aY).
Upewnij się, że kąty, które obliczasz, zawsze są w radianach.
Jeśli musisz obliczyć promień okręgu, możesz użyć odejmowania wektora, odjąć punkt „c” od punktu „o”, a następnie uzyskać długość wynikowego wektora.
Uważam, że coś takiego powinno zrobić. Nie znam Java, więc zgadłem, jaka jest dokładna składnia.
Oto obraz podany przez użytkownika w
Byte56
celu zilustrowania wyglądu tego trójkąta:źródło
Aby obrócić obiekt obj2 wokół obiektu obj1, spróbuj:
źródło