Wofür werden atan und atan2 in Spielen verwendet?


47

Ich habe einige Probleme beim Verstehen von Math.tan()und Math.atan()und Math.atan2().

Ich habe Grundkenntnisse in Trigonometrie, aber die Verwendung von SIN, COS und TAN usw. für die Spieleentwicklung ist für mich sehr neu.

Ich lese in einigen Tutorials und sehe, dass wir mit Tangente den Winkel ermitteln können, in dem ein Objekt gedreht werden muss, um zu sehen, wie weit es einem anderen Objekt zugewandt ist, zum Beispiel meiner Maus. Warum müssen wir also noch atan oder atan2 verwenden?


Mit atan wird der Winkel bestimmt, der für tausend verschiedene Dinge nützlich ist. Haben Sie eine konkrete Frage zur Verwendung oder suchen Sie nur allgemeine mathematische Hilfe?
BlueRaja - Danny Pflughoeft

5
Sie müssen auf jeden Fall die Mathematik / Geometrie hinter diesen Funktionen verstehen. Sobald Sie sie beherrschen, werden sie Teil Ihres "Weltverständnisses", wie die grundlegende Grammatik, die Sie täglich zum Sprechen verwenden. Sobald Sie in der Lage sind, "die Mathematik / Geometrie zu sprechen", werden Sie sehen, dass diese Funktionen einfache Werkzeuge sind, um ein Ergebnis zu erzielen, das am natürlichsten zu verwenden ist.
FxIII

Diese Tutorials sind entweder falsch oder Sie haben sie falsch verstanden. Sie verwenden atan2 (), um den Winkel von einem Objekt zum anderen zu ermitteln. Wie das geht, erfahren Sie weiter unten.
jhocking

Antworten:


93

Die Tangentenformel lautet:

tan(angle) = opposite/adjacent

Beziehen Sie sich auf diese Zeichnung:

Diagramm eines rechtwinkligen Dreiecks, mit einem Winkel Theta und seinen gegenüberliegenden und benachbarten Seiten markiert

Wo aist die benachbarte Seite, oist die gegenüberliegende Seite und thetaist der Winkel. In ähnlicher Weise sind Sinus und Cosinus sin (ang) = o / h und cos (ang) = a / h, wobei hdie lange Seite lautet: http://www.mathwords.com/s/sohcahtoa.htm

In der Zwischenzeit atan(Abkürzung für Arcustangens , auch als inverser Tangens bezeichnet ) ist das Gegenteil von tan:

atan(opposite/adjacent) = angle

Wenn Sie also die Werte der gegenüberliegenden und benachbarten Seiten kennen (z. B. durch Subtrahieren der Objektkoordinaten von den Mauskoordinaten), können Sie den Wert des Winkels mit ermitteln atan.

In der Spielentwicklung kann es jedoch ziemlich häufig vorkommen, dass die benachbarte Seite gleich 0 ist (z. B. wenn die x-Koordinate eines Vektors 0 ist). Denken Sie daran, dass tan(angle) = opposite/adjacentdas Potenzial für einen katastrophalen Fehler bei der Division durch Null klar sein sollte. Viele Bibliotheken bieten daher eine Funktion namens an atan2, mit der Sie die Parameter xund angeben ykönnen, um die Division durch Null für Sie zu vermeiden und einen Winkel im rechten Quadranten anzugeben .

atan2 Diagramm

(Diagramm mit freundlicher Genehmigung von Gareth, bitte stimmen Sie auch seine Antwort ab)


Die Verwendung von Trigonometrie in der Spieleentwicklung ist besonders bei Vektoren sehr verbreitet, aber in der Regel verbergen Bibliotheken die Trigonometriearbeit für Sie. Sie können sin / cos / tan für viele Aufgaben verwenden, bei denen geometrische Manipulationen erforderlich sind, um einen Wert aus einem Dreieck zu ermitteln. Alles, was Sie brauchen, sind 3 Werte (Seitenlängen / Winkelwerte), um die anderen Werte eines Rechteckdreiecks zu finden.

Sie können sogar die "zyklische" Natur der Sinus- und Cosinus-Funktionen für spezielle Verhaltensweisen in einem Spiel verwenden, z.


8
Es ist erwähnenswert, dass Wikipedia andere Verwendungen für Atan2 ( nicht Atan) beschreibt, als nur die Division durch Null zu vermeiden. Zum Beispiel korrigiert es sich selbst für den verwendeten Quadranten, wo Sie das normalerweise alles selbst tun müssten.
Doppelgreener

In der Tat sehr wichtiger Hinweis genau dort. Aktualisiere meine Antwort.
Jesse Emond

Haben Sie sich in Ihrem ersten langen Absatz nicht rückwärts gebräunt? Sie würden atan verwenden, um den Winkel zu ermitteln (dh die Gleichung umzukehren) und tan, um das Verhältnis der Seiten zu ermitteln (dh genau das, was die Gleichung sagt).
jhocking

Nun, wenn Sie wissen, dass O / A gleich zB 3 ist, dann ist es das, was ich gemeint habe, wenn Sie den Winkel machen wollen, wenn Sie den Winkel isolieren wollen, verwenden Sie atan für das Verhältnis. Wenn Sie das Verhältnis isolieren möchten, verwenden Sie tan für den Winkel.
Jesse Emond

Ich werde dann deine Formulierung ändern, weil es so klingt, als würdest du das Gegenteil sagen.
jhocking

63

Bildbeschreibung hier eingeben


1
Wäre es unhöflich, die oberste Antwort zu bearbeiten, um dieses Diagramm darin zu haben? Dieses Diagramm ist großartig und würde gut nach Jesses schriftlicher Erklärung von atan2 () passen.
jhocking

1
Los, sei mein Gast! Ich werde diese Antwort löschen, wenn Sie fertig sind.
Gareth Rees

7
Nein nein Mach weiter! Es wird gutgeschrieben und die Leute sollten hier noch für das Diagramm stimmen.
Jesse Emond

12

Hier ist eine etwas andere Art, über Triggerfunktionen nachzudenken - einschließlich atan () und atan2 () -, die ich hilfreich finde (Erklärungen in Bezug auf "Gegenteil / Nebeneinander" verwirren mich nur aus irgendeinem Grund).

x, y, r, Theta

Sie können von einem Punkt zum anderen gelangen, indem Sie x- Einheiten horizontal und y- Einheiten vertikal verschieben ( Rechteck- oder kartesische Koordinaten genannt) oder die Strecke r in einem Winkel von Ɵ verschieben ( in 2D Polarkoordinaten genannt ).

Angenommen, wir haben eine Polarkoordinate (r, Ɵ) und möchten sie in (x, y) konvertieren.

cos (Ɵ) gibt den Anteil von r an , der entlang der x- Achse liegt:

  • Wenn r = 1, dann ist x = cos (().
  • Wenn r = 100, dann ist x = 100 · cos (Ɵ).
  • Im Allgemeinen ist x = r * cos (Ɵ).

Ebenso gibt sin (Ɵ) den Anteil von r an , der entlang der y- Achse liegt:

  • Wenn r = 1, dann ist y = sin (().
  • Wenn r = 100, dann ist y = 100 * sin (Ɵ).
  • Im Allgemeinen ist y = r * sin (Ɵ).

Wie wäre es, rechteckige Koordinaten (x, y) in Polarkoordinaten (r, Ɵ) umzuwandeln?

r ist die Hypotenuse des aus x und y gebildeten rechtwinkligen Dreiecks , also:

  • r = sqrt (x x + y y)

tan (Ɵ) gibt die Steigung - den Anstieg über den Verlauf - der Linie mit der Länge r an . Damit:

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

Wenn Sie jedoch y / x ausführen, ergibt die Berechnung von 3/4 die gleiche Antwort wie die Berechnung von -3 / -4. Ebenso gibt -3/4 die gleiche Antwort wie 3 / -4. Wir haben also atan2 (y, x), das die einzelnen Vorzeichen korrekt behandelt und einen Fehler durch Null / Unendlich verhindert.

  • Ɵ = atan2 (y, x)

4

Jesse und Sid haben im Grunde recht, aber ich vermute, Sie sind wirklich auf der Suche nach Einsicht in das Problem.

Atan2 () wird benötigt, da atan () Ihnen nicht den Winkel von der Horizontalen angibt, den Sie benötigen, da es nicht mit Quadranten zurechtkommt.

Dies bedeutet, dass die Verwendung von atan für die Vektoren (-2,2) und (2, -2) den gleichen Wert ergibt. Sie würden dann das Vorzeichen Ihrer Argumente einschalten und pi zum Ergebnis hinzufügen. Darüber hinaus haben Sie den Sonderfall der Division durch Null zu berücksichtigen, dass Jesse erwähnt. Auch atan2 () funktioniert besser als atan, wenn x nahe 0 ist

Also du, wenn du den Winkel eines Vektors zwischen -pi und pi willst

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

oder

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

1
"Dies bedeutet, dass die Verwendung von atan für die Vektoren (-2,2) und (2,2) den gleichen Wert ergibt." Wenn dies der Fall ist, ist Ihr atan unglaublich gebrochen, weil einer von ihnen -π / 4 und der andere π / 4 sein sollte. Schande über alle, die diesen Müll gewählt haben.

Der Code ist immer noch falsch. Sie testen, y==0ob Sie dann xin der anderen Branche durch dividieren .
Sam Hocevar

0

Ich werde ein paar Dinge kurz erläutern. Eine ausführliche Erklärung finden Sie in den Online-Tutorials zur Trigonometrie.

Sei a ein Winkel. Dann ist tan (a) = tan (a + 2 * pi).

atan ist tan invers, das heißt, Sie erhalten den Winkel, der der tan gegeben ist. Wenn Sie atan (tan (a + 2 * pi)) anrufen, lautet die Antwort a. Dies ist für Ihre Anwendung nicht ausreichend.

atan2 benötigt zwei Argumente, um genau diese Situation zu unterstützen. atan nimmt x und y, die im Grunde genommen cos (a) und sin (a) sind.

atan2 (sin (a), cos (a)) = a atan2 (sin (a + 2 * pi), cos (a + 2 * pi)) = a + 2 * pi / * sin und cos haben unterschiedliche Vorzeichen und führen zu einer anderen Antwort * /

In einigen Tutorials erfahren Sie, warum dies so ist.

Ihr Code sollte ungefähr so ​​aussehen:

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
}

tan(a) = - tan(-a)Die Gleichung, die Sie ausdrücken wollten, war vielleichttan(a) = tan(pi+a)
Ali1S232

0

Eine Verwendung, die atan2ich in meinem Code gefunden habe, ist "Winkel mit Vorzeichen".

Normalerweise wird der Winkel zwischen zwei Vektoren wie folgt ermittelt

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

Dies sagt Ihnen aber nicht, welcher "führt" (dh "weiter vorne im Uhrzeigersinn" als der andere). Diese Informationen können für die Gestenverfolgung wichtig sein.

Sie könnten den Winkel von der x-Achse (1,0)für beide Vektoren finden, aber es gibt das schlimme Problem der Mehrdeutigkeit: Ein Vektor mit einem Winkel von 315 Grad gibt mit der cosoben beschriebenen Methode 45 Grad zurück , ebenso ein Winkel von 45 Grad. Sie könnten eine Überprüfung der Zeichen durchführen, um das yzu beheben, oder Sie könnten verwenden 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 ;
}

0

Bitte beachten Sie, dass atan nicht defekt ist. arctan oder tan invers ist nur eine Funktion zwischen -PI / 2 und PI / 2. Es wiederholt dieses Muster, ist aber keine Funktion, die für einen Computer ein Problem darstellt, da es nicht mit Mehrfachantworten umgehen kann.

Dies gilt auch zwischen -PI / 2 und PI / 2 und acos zwischen 0 und PI. Dies sind die einfachsten Bereiche für das Auftreten einer Funktion. Für Atan und Asin geht es von seinem negativsten zu seinem positivsten. Für acos geht es vom Positivsten zum Negativsten. (Dies hilft bei der Interpolation genauerer Antworten)

also sind asin, acos und atan die mathematischen funktionen.

atan2 ist jedoch für die Programmierung viel nützlicher, da es die vollständige Umdrehung liefert (PI im Bogenmaß oder 360 Grad oder 400 Grad). Beachten Sie, dass sie nur eine für Bräune produzierten, nicht für Sünde oder Lattich. Tan ist die einzige, die horizontal und vertikal verwendet (x, y)

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.