À quoi servent atan et atan2 dans les jeux?


48

J'ai du mal à comprendre Math.tan()et Math.atan()et Math.atan2().

J'ai des connaissances de base en trigonométrie, mais l'utilisation du NAS, du COS, du TAN, etc. pour le développement de jeux est très nouvelle pour moi.

Je lis des tutoriels et je vois qu'en utilisant la tangente, nous pouvons obtenir l'angle dans lequel un objet doit être pivoté de combien de visages pour faire face à un autre objet, par exemple ma souris. Alors pourquoi avons-nous toujours besoin d'utiliser atan ou atan2?


atan est utilisé pour déterminer l'angle, utile pour mille choses différentes. Avez-vous une question à propos de son utilisation ou cherchez-vous simplement de l'aide en mathématiques générales?
BlueRaja - Danny Pflughoeft

5
Vous devez absolument comprendre les mathématiques / la géométrie derrière ces fonctions; une fois que vous les maîtriserez, ils feront partie de votre "compréhension du monde", comme la grammaire de base que vous utilisez tous les jours pour parler. Une fois que vous êtes capable de "parler mathématique / géométrique", vous verrez que ces fonctions sont de simples outils pour obtenir un résultat, le plus naturel à utiliser.
FxIII

Ces tutoriels sont soit incorrects, soit incompris. Vous utilisez atan2 () pour obtenir l'angle d'un objet à un autre. Comment cela fonctionne est expliqué ci-dessous.
Jhocking

remercie les gens pour les réponses, je regrette maintenant de ne pas avoir prêté plus d'attention en classe
sutoL

Réponses:


94

La formule tangente est la suivante:

tan(angle) = opposite/adjacent

Reportez-vous à ce dessin:

Schéma d'un triangle rectangle, avec un angle thêta et ses côtés opposés et adjacents marqués

aest le côté adjacent, oest le côté opposé et thetal'angle. De même, sinus et cosinus sont un péché (ang) = o / h et cos (ang) = a / h où se htrouve le côté long: http://www.mathwords.com/s/sohcahtoa.htm

Pendant ce temps atan(abréviation de arc-tangente , également appelée tangente inverse ) est l'inverse de tan, comme ceci:

atan(opposite/adjacent) = angle

Ainsi, si vous connaissez les valeurs des côtés opposé et adjacent (par exemple, en soustrayant les coordonnées de l'objet des coordonnées de la souris), vous pouvez obtenir la valeur de l'angle avec atan.

Cependant, dans le développement de jeux, il peut arriver assez souvent que le côté adjacent soit égal à 0 (par exemple, la coordonnée x d'un vecteur étant 0). Il ne faut pas oublier que tan(angle) = opposite/adjacentla possibilité d'une erreur catastrophique de division par zéro devrait être évidente. Donc , beaucoup de bibliothèques offrent une fonction appelée atan2, ce qui vous permet de spécifier les deux xet les yparamètres, afin d' éviter la division par zéro pour vous et donner un angle dans le quadrant droit.

diagramme atan2

(diagramme avec la permission de gareth, votez s'il vous plaît sa réponse aussi)


L'utilisation de la trigonométrie dans le développement de jeux est assez courante, en particulier avec les vecteurs, mais les bibliothèques cachent généralement le travail de trigonométrie pour vous. Vous pouvez utiliser sin / cos / tan pour un grand nombre de tâches impliquant des manipulations géométriques pour trouver une valeur à partir d'un triangle. Tout ce dont vous avez besoin est de 3 valeurs (longueurs de côté / valeurs d'angle) pour trouver les autres valeurs d'un triangle rectangle, c'est donc très utile.

Vous pouvez même utiliser la nature "cycliste" des fonctions sinus et cosinus pour des comportements particuliers dans un jeu. Par exemple, j'ai vu cos / sin utilisé pour faire en sorte qu'un objet tourne autour d'un autre.


8
Il est à noter que Wikipedia décrit d' autres utilisations pour Atan2 ( pas Atan), à savoir simplement éviter la division par zéro. Par exemple, il se corrige lui-même pour le quadrant utilisé, où vous devez normalement faire tout cela vous-même.
doppelgreener

En effet, note très importante juste là. Mise à jour de ma réponse.
Jesse Emond

N'avez-vous pas bronzé et retourné dans votre premier long paragraphe? Vous utiliseriez atan pour obtenir l'angle (c'est-à-dire inverser l'équation) et le bronzage pour obtenir le rapport des côtés (c'est-à-dire exactement ce que l'équation dit).
Jhocking

Eh bien, si vous savez que o / a est égal à 3, alors si vous voulez l'angle que vous faites atan (3), c'est ce que je voulais dire: si vous voulez isoler l'angle, vous utilisez atan sur le rapport. Si vous souhaitez isoler le rapport, vous utilisez le bronzage sur l'angle.
Jesse Emond

Je vais changer votre libellé alors, car il semblerait que vous disiez le contraire.
Jhocking

64

entrez la description de l'image ici


1
Serait-il impoli de modifier la réponse en haut pour avoir ce diagramme? Ce diagramme est génial et conviendrait bien après l'explication écrite de jesse de atan2 ().
Jhocking

1
Allez-y: soyez mon invité! Je vais supprimer cette réponse une fois que vous avez terminé.
Gareth Rees

7
Non non. Continuez! Il est crédité et les gens devraient toujours voter ici pour le diagramme.
Jesse Emond

12

Voici une façon légèrement différente de penser aux fonctions trigonométriques - y compris atan () et atan2 () - que je trouve utiles (les explications en termes de "opposé / adjacent" me déroutent pour une raison quelconque).

x, y, r, thêta

Vous pouvez aller d'un point à un autre en déplaçant x unités horizontalement et y unités verticalement ( coordonnées rectangulaires ou cartésiennes ) ou en déplaçant la distance r à un angle de Ɵ ( coordonnées polaires en 2D).

Supposons que nous avons une coordonnée polaire (r, Ɵ) et que nous souhaitons la convertir en (x, y).

cos () vous donne la proportion de r qui se trouve le long de l' axe des x :

  • Si r = 1 alors x = cos ().
  • Si r = 100 alors x = 100 * cos ().
  • En général, x = r * cos ().

De même, sin () vous donne la proportion de r qui se trouve le long de l’ axe des y :

  • Si r = 1 alors y = péché ().
  • Si r = 100 alors y = 100 * sin ().
  • En général, y = r * sin ().

Que diriez-vous de convertir des coordonnées rectangulaires (x, y) en coordonnées polaires (r, Ɵ)?

r est l'hypoténuse du triangle rectangle formé par x et y , donc:

  • r = sqrt (x x + y y)

tan () donne la pente - la montée sur la longueur - de la droite de longueur r . Alors:

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

Cependant, lors de l'exécution de y / x, le calcul de 3/4 donne la même réponse que le calcul de -3 / -4. De même, -3 / 4 donne la même réponse que 3 / -4. Nous avons donc atan2 (y, x) qui gère correctement les signes individuels et empêche une erreur de division par zéro / infini.

  • = Atan2 (y, x)

4

Jesse et Sid ont fondamentalement raison, mais je suppose que vous voulez vraiment comprendre le problème.

Atan2 () est nécessaire car atan () ne vous indique pas l'angle par rapport à l'horizontale dont vous avez besoin, car il ne gère pas les quadrants.

Cela signifie que l'utilisation de atan pour les vecteurs (-2,2) et (2, -2) donnera la même valeur. Vous devez alors activer le signe de vos arguments et ajouter pi au résultat. De plus, vous avez le cas particulier de la division par zéro à considérer que Jesse a mentionné. Atan2 () fonctionne également mieux que atan lorsque x est proche de 0

Donc, si vous voulez l'angle d'un vecteur entre -pi et pi

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

ou

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
"Cela signifie que l'utilisation de atan pour les vecteurs (-2,2) et (2,2) donnera la même valeur." Si tel est le cas, votre atan est incroyablement cassé, car l’un d’eux devrait être -π / 4 et l’autre π / 4. Honte à tous ceux qui ont voté pour le pire

Le code est toujours faux. Vous testez y==0puis divisez par xdans l'autre branche.
Sam Hocevar

0

Je vais clarifier quelques points de manière concise. Veuillez vous reporter aux didacticiels de trigonométrie en ligne pour une explication détaillée.

Soit a un angle. Puis tan (a) = tan (a + 2 * pi).

atan est tan inverse, c’est-à-dire vous donne l’angle donné au bronzage. Lorsque vous appelez atan (tan (a + 2 * pi)), la réponse sera a. Ce sera inadéquat pour votre application.

atan2 prendra 2 arguments pour aider cette situation exacte. atan prend x et y, qui sont fondamentalement cos (a) et sin (a).

atan2 (sin (a), cos (a)) = a atan2 (sin (a + 2 * pi), cos (a + 2 * pi)) = a + 2 * pi / * sin et cos a des signes différents, conduisant à une réponse différente * /

Veuillez trouver quelques tutoriels pour expliquer pourquoi c'est ainsi.

Votre code devrait ressembler à ceci:

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), l'équation que vous vouliez exprimer était peuttan(a) = tan(pi+a)
Ali1S232

0

Une utilisation car atan2je trouve dans mon code est "angle signé".

Normalement, l’angle entre deux vecteurs est défini comme suit:

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

Mais cela ne vous dit pas lequel "mène" (c'est-à-dire "plus loin dans le sens des aiguilles d'une montre" que l'autre). Cette information peut être importante pour le suivi des gestes.

Vous pouvez trouver l’angle à partir de l’axe x (1,0)pour les deux vecteurs, mais il existe un problème d’ambiguïté: un vecteur avec un angle de 315 degrés renvoie 45 degrés avec la cosméthode ci-dessus, de même que l’angle 45 °. Vous pouvez faire une vérification des panneaux ypour résoudre ce problème, ou vous pouvez utiliser 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

S'il vous plaît noter atan n'est pas cassé. arctan ou tan inverse n’est une fonction que entre -PI / 2 et PI / 2. Il répète ce modèle, mais ce n’est pas une fonction qui pose problème à un ordinateur car il ne gère pas plusieurs réponses.

C'est la même chose pour asin entre -PI / 2 et PI / 2 et acos entre 0 et PI. Ce sont les plages les plus simples pour qu'une fonction se produise. Pour atan et asin, il passe du plus négatif au plus positif. Pour acos, il passe du plus positif au plus négatif. (cela aide à interpoler des réponses plus précises)

donc asin, acos et atan sont les fonctions mathématiques.

atan2 est cependant beaucoup plus utile pour la programmation car il fournit la révolution complète (PI en radians ou 360 degrés ou 400 gradians). Notez qu'ils n'en produisent qu'un pour le bronzage, pas pour le péché ou le cos. Tan est le seul qui utilise horizontal et vertical (x, y)

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.