Do czego służą atan i atan2 w grach?

47

Mam pewne problemy ze zrozumieniem Math.tan()i Math.atan()i Math.atan2().

Mam podstawową wiedzę na temat trygonometrii, ale użycie SIN, COS i TAN itp. Do tworzenia gier jest dla mnie bardzo nowe.

Czytam niektóre samouczki i widzę, że używając stycznej możemy uzyskać kąt, pod którym jeden obiekt musi zostać obrócony, o ile jest skierowany w stronę innego obiektu, na przykład mojej myszy. Dlaczego więc nadal musimy używać atan lub atan2?

sutoL
źródło
Atan służy do określania kąta, przydatnego dla tysiąca różnych rzeczy. Czy masz rzeczywiste pytanie dotyczące jego wykorzystania, czy po prostu szukasz ogólnej pomocy matematycznej?
BlueRaja - Danny Pflughoeft
5
Zdecydowanie musisz zrozumieć matematykę / geometrię stojącą za tymi funkcjami; kiedy je opanujesz, staną się częścią twojego „rozumienia świata”, podobnie jak podstawowa gramatyka, której używasz na co dzień, aby mówić. Kiedy będziesz w stanie „mówić matematykę / geometrię”, zobaczysz, że te funkcje są prostymi narzędziami do osiągnięcia wyniku, najbardziej naturalnym w użyciu.
FxIII
Te samouczki są błędne lub źle zrozumiane. Użyj atan2 (), aby uzyskać kąt od jednego obiektu do drugiego. Jak to działa, wyjaśniono poniżej.
jhocking
dziękuję ludziom za odpowiedzi, teraz żałuję, że nie zwracałem większej uwagi w klasie
sutoL

Odpowiedzi:

93

Wzór na styczną jest następujący:

tan(angle) = opposite/adjacent

Zobacz ten rysunek:

Schemat trójkąta prostokątnego z zaznaczonym kątem theta i jego przeciwległymi i sąsiadującymi bokami

Gdzie ajest strona sąsiednia, ojest stroną przeciwną i thetakątem. Podobnie, sinus i cosinus to sin (ang) = o / hi cos (ang) = a / h gdzie hjest długa strona: http://www.mathwords.com/s/sohcahtoa.htm

Tymczasem atan(skrót od stycznej do łuku , znany również jako styczna odwrotna ) jest odwrotnością tan:

atan(opposite/adjacent) = angle

Tak więc, jeśli znasz wartości zarówno przeciwnej, jak i sąsiedniej strony (na przykład odejmując współrzędne obiektu od współrzędnych myszy), możesz uzyskać wartość kąta za pomocą atan.

W rozwoju gry może się jednak zdarzyć dość często, że sąsiednia strona jest równa 0 (np. Współrzędna x wektora wynosi 0). Pamiętając, że tan(angle) = opposite/adjacentpotencjał katastrofalnego błędu dzielenia przez zero powinien być jasny. Tak więc wiele bibliotek oferuje funkcję o nazwie atan2, która pozwala określić zarówno parametry, jak xi yparametry, aby uniknąć podziału na zero i dać kąt we właściwej ćwiartce.

schemat atan2

(schemat dzięki uprzejmości Garetha, proszę również głosować na jego odpowiedź)


Zastosowanie trygonometrii w tworzeniu gier jest dość powszechne, szczególnie w przypadku wektorów, ale zwykle biblioteki ukrywają dla ciebie pracę trygonometrii. Możesz użyć sin / cos / tan do wielu zadań, które wymagają manipulacji geometrycznych w celu znalezienia wartości z trójkąta. Potrzebujesz tylko 3 wartości (długości boków / wartości kątów), aby znaleźć inne wartości trójkąta prostokątnego, więc jest to całkiem przydatne.

Możesz nawet użyć „cyklicznej” natury funkcji sinus i cosinus do specjalnych zachowań w grze, np. Widziałem, że cos / sin często używał, aby obiekt obracał się wokół innego.

Jesse Emond
źródło
8
Warto zauważyć, że Wikipedia opisuje inne zastosowania Atan2 ( nie atan) niż tylko unikanie dzielenia przez zero. Na przykład koryguje się dla używanego kwadrantu, gdzie normalnie musiałbyś zrobić to wszystko sam.
doppelgreener
Rzeczywiście, bardzo ważna uwaga tutaj. Aktualizacja mojej odpowiedzi.
Jesse Emond
Czy w pierwszym długim akapicie nie opaliłeś się i nie miałeś oporu? Użyłbyś atan, aby uzyskać kąt (tj. Odwrócić równanie) i tan, aby uzyskać stosunek boków (tj. Dokładnie to, co mówi równanie).
jhocking
Cóż, jeśli wiesz, że o / a jest równe np. 3, to jeśli chcesz kąt, który wykonujesz atan (3), to właśnie miałem na myśli: jeśli chcesz wyizolować kąt, użyj atan na stosunku. Jeśli chcesz wyodrębnić proporcje, użyj opalenizny na kącie.
Jesse Emond
Zmienię wtedy twoje sformułowanie, ponieważ brzmi to tak, jakbyś powiedział coś przeciwnego.
jhocking
63

wprowadź opis zdjęcia tutaj

Gareth Rees
źródło
1
Czy niegrzeczne byłoby edytowanie najlepszej odpowiedzi, aby mieć w niej ten schemat? Ten schemat jest świetny i pasuje dobrze zaraz po pisemnym wyjaśnieniu Jesse'a o atan2 ().
jhocking
1
Śmiało: bądź moim gościem! Usunę tę odpowiedź po zakończeniu.
Gareth Rees,
7
Nie? Nie. Tak trzymaj! Jest przypisany i ludzie powinni nadal głosować tutaj za diagramem.
Jesse Emond
12

Oto nieco inny sposób myślenia o funkcjach triggera - w tym atan () i atan2 () - który uważam za pomocny (wyjaśnienia w kategoriach „przeciwieństwo / sąsiadowanie” po prostu mylą mnie z jakiegoś powodu).

x, y, r, theta

Możesz przejść z jednego punktu do drugiego, przesuwając x jednostek w poziomie, a y jednostek w pionie (zwanych współrzędnymi prostokątnymi lub kartezjańskimi ) lub przesuwając odległość r pod kątem Ɵ (zwanym współrzędnymi biegunowymi w 2D).

Powiedzmy, że mamy współrzędną biegunową (r, Ɵ) i chcemy ją przekonwertować na (x, y).

cos (Ɵ) daje ci proporcję r, która leży wzdłuż osi x :

  • Jeśli r = 1, to x = cos (Ɵ).
  • Jeśli r = 100, to x = 100 * cos (Ɵ).
  • Ogólnie x = r * cos (Ɵ).

Podobnie sin (Ɵ) daje ci proporcję r, która leży wzdłuż osi y :

  • Jeśli r = 1, to y = sin (Ɵ).
  • Jeśli r = 100, to y = 100 * sin (Ɵ).
  • Ogólnie y = r * sin (Ɵ).

Co powiesz na przekształcenie współrzędnej prostokątnej (x, y) na współrzędną biegunową (r, Ɵ)?

R jest przeciwprostokątna trójkąta prostokątnego utworzonego przez X i Y , tak:

  • r = sqrt (x x + y y)

tan (Ɵ) daje nachylenie - wzrost w biegu - linii o długości r . Więc:

  • tan (Ɵ) = y / x
  • Ɵ = atan (t / x)

Jednak wykonując y / x, obliczenie 3/4 daje taką samą odpowiedź jak obliczenie -3 / -4. Podobnie -3/4 daje taką samą odpowiedź jak 3 / -4. Mamy więc atan2 (y, x), który poprawnie obsługuje poszczególne znaki i zapobiega błędowi dzielenia przez zero / nieskończoności.

  • Ɵ = atan2 (y, x)
AbePralle
źródło
4

Jesse i Sid mają w zasadzie rację, ale podejrzewam, że naprawdę masz wgląd w problem.

Atan2 () jest potrzebny, ponieważ atan () nie mówi ci kąta od poziomu, którego potrzebujesz, ponieważ nie radzi sobie z ćwiartkami.

Oznacza to, że użycie atan dla wektorów (-2,2) i (2, -2) da tę samą wartość. Następnie należy włączyć znak argumentów i dodać wynik do pi. Ponadto masz dzielony przez zero szczególny przypadek, aby wziąć pod uwagę wspomniany przez Jesse'a. Również atan2 () działa lepiej niż atan, gdy x jest bliskie 0

Więc jeśli chcesz kąt wektora między -pi a pi

x = -2
y = 2
angle = Math.Atan2(y, x)

lub

x = -2
y = 2
angle = calculateAngle(y, x);

double CalculateAngle(double y, double x)
{
    double angle = 0;
    if (x == 0)
    {
        if (y == 0)
            angle = 0;
        else if (y > 0)
            angle = Math.PI/2;
        else
            angle = -Math.PI/2;
    }
    else
    {
        angle = Math.Atan(y/x);
        if (x < 0)
        {
            if (y > 0)
            {
                angle += Math.PI;
            }
            else if (y < 0)
            {
                angle -= Math.PI;
            }
            else
            {
                angle = Math.PI;
            }
        }
    }
    return angle;
}
LukeN
źródło
1
„Oznacza to, że użycie atan dla wektorów (-2,2) i (2,2) da tę samą wartość.” Jeśli tak jest, twój atan jest niesamowicie zepsuty, ponieważ jednym z nich powinno być -π / 4, a drugim π / 4. Wstyd wszystkim, którzy głosowali na te śmieci.
Kod jest nadal niepoprawny. Testujesz pod kątem y==0dzielenia się xw drugiej gałęzi.
sam hocevar,
0

Wyjaśnię kilka rzeczy w zwięzły sposób. Szczegółowe wyjaśnienia znajdują się w samouczkach trygonometrii online.

Niech będzie kąt. Następnie tan (a) = tan (a + 2 * pi).

atan jest podpalany odwrotnie, to znaczy daje kąt podany opaleniu. Gdy zadzwonisz do atan (tan (a + 2 * pi)), odpowiedzią będzie. Będzie to nieodpowiednie dla twojej aplikacji.

atan2 przyjmie 2 argumenty, aby pomóc w tych dokładnych sytuacjach. Atan przyjmuje xiy, które są w zasadzie cos (a) i sin (a).

atan2 (sin (a), cos (a)) = a atan2 (sin (a + 2 * pi), cos (a + 2 * pi)) = a + 2 * pi / * sin i cos ma różne znaki, prowadzące na inną odpowiedź * /

Znajdź kilka samouczków wyjaśniających, dlaczego tak jest.

Twój kod powinien być mniej więcej taki:

if (mouseMoved)
{
  double angle = atan2(mousey - objecty, mousex - objectx);

  object. setTransform to Rotate(angle);

  // If you want to print it
  print radian_to_degrees(angle); // Because angle is in radian 360 degrees = 2*Pi radians
}
Sid Datta
źródło
tan(a) = - tan(-a), równanie, które chciałeś wyrazić, to być możetan(a) = tan(pi+a)
Ali1S232,
0

Jednym z zastosowań atan2, które znalazłem w moim kodzie, jest „kąt podpisany”.

Normalnie sposób, w jaki można znaleźć kąt między dwoma wektorami, jest

inline float angleWith( const Vector2f& o ) const
{
    return acosf( this->normalizedCopy().dot(o.normalizedCopy()) ) ;
}

Ale to nie mówi ci, który z nich „prowadzi” (tj. Jest „dalej naprzód zgodnie z ruchem wskazówek zegara” niż drugi). Informacje te mogą być ważne dla śledzenia gestów.

Można znaleźć kąt od osi x (1,0)dla obu wektorów, ale istnieje ten paskudny problem niejednoznaczności: wektor o kącie 315 stopni zwraca 45 stopni przy użyciu cospowyższej metody, podobnie jak kąt 45 stopni. Możesz to zrobić, yaby to naprawić, lub możesz użyć atan2.

// Returns + if this leads o.
// more expensive than unsigned angle.
inline float signedAngleWith( const Vector2f& o ) const
{
  float aThis = atan2f( y, x );
  float aO = atan2f( o.y, o.x ) ;
  return aThis - aO ;
}
Bobobobo
źródło
0

Uwaga: atan nie jest zepsuty. arctan lub tan inverse jest tylko funkcją między -PI / 2 a PI / 2. Powtarza ten wzorzec, ale nie jest to funkcja stanowiąca problem dla komputera, ponieważ nie obsługuje wielu odpowiedzi.

Jest to to samo dla asin między -PI / 2 i PI / 2 i acos między 0 i PI. Są to najprostsze zakresy dla wystąpienia funkcji. W przypadku atanu i asinu przechodzi od najbardziej negatywnego do najbardziej pozytywnego. W przypadku acos zmienia się od najbardziej pozytywnego do najbardziej negatywnego. (pomaga to w interpolacji dokładniejszych odpowiedzi)

więc asin, acos i atan są funkcjami matematycznymi.

atan2 jest jednak znacznie bardziej użyteczny do programowania, ponieważ zapewnia pełny obrót (PI w radianach lub 360 stopniach lub 400 gradianach). Zauważ, że wyprodukowali tylko jeden dla opalenizny, a nie dla grzechu lub cos. Tan jest jedynym, który wykorzystuje poziomy i pionowy (x, y)

Licho
źródło