¿Para qué se utilizan atan y atan2 en los juegos?

48

Tengo problemas para entender Math.tan()y Math.atan()y Math.atan2().

Tengo conocimientos básicos de trigonmetría, pero el uso de SIN, COS, TAN, etc. para el desarrollo de juegos es muy nuevo para mí.

Estoy leyendo algunos tutoriales y veo que mediante el uso de la tangente podemos obtener el ángulo en el que un objeto necesita ser girado en función de cuánto se enfrenta a otro objeto, por ejemplo, mi mouse. Entonces, ¿por qué todavía necesitamos usar atan o atan2?

sutoL
fuente
atan se usa para determinar el ángulo, útil para mil cosas diferentes. ¿Tiene una pregunta real sobre su uso o simplemente está buscando ayuda matemática general?
BlueRaja - Danny Pflughoeft
55
Definitivamente necesita comprender las matemáticas / geometría detrás de esas funciones; una vez que los domines, se convertirán en parte de tu "comprensión del mundo", como la gramática básica que usas todos los días para hablar. Una vez que pueda "hablar matemática / geometría" verá que esas funciones son herramientas simples para lograr un resultado, lo más natural de usar.
FxIII
Esos tutoriales están equivocados o lo malentendieron. Utiliza atan2 () para obtener el ángulo de un objeto a otro. Cómo funciona eso se explica a continuación.
jhocking
la gente gracias por las respuestas, ahora estoy lamentando no prestar más atención en clase
sutoL

Respuestas:

94

La fórmula tangente es esta:

tan(angle) = opposite/adjacent

Consulte este dibujo:

Diagrama de un triángulo rectángulo, con un ángulo theta y sus lados opuestos y adyacentes marcados

Donde aestá el lado adyacente, oes el lado opuesto y thetaes el ángulo. Del mismo modo, seno y coseno son sin (ang) = o / hy cos (ang) = a / h, donde hestá el lado largo: http://www.mathwords.com/s/sohcahtoa.htm

Mientras tanto atan(abreviatura de arco-tangente , también conocida como la tangente inversa ) es lo contrario de tan, así:

atan(opposite/adjacent) = angle

Por lo tanto, si conoce los valores de los lados opuestos y adyacentes (por ejemplo, restando las coordenadas del objeto de las coordenadas del mouse) puede obtener el valor del ángulo con atan.

Sin embargo, en el desarrollo del juego, puede ocurrir con bastante frecuencia que el lado adyacente sea igual a 0 (por ejemplo, la coordenada x de un vector es 0). Recordando que tan(angle) = opposite/adjacentel potencial de un desastroso error de división por cero debería ser claro. Por lo tanto, muchas bibliotecas ofrecen una función llamada atan2, que le permite especificar los parámetros xy y, para evitar la división por cero y proporcionar un ángulo en el cuadrante derecho.

diagrama de atan2

(diagrama cortesía de gareth, por favor vote su respuesta también)


El uso de trigonometría en el desarrollo de juegos es bastante común, especialmente con vectores, pero generalmente las bibliotecas ocultan el trabajo de trigonometría para usted. Puede usar sin / cos / tan para muchas tareas que involucran manipulaciones geométricas para encontrar un valor de un triángulo. Todo lo que necesitas son 3 valores (longitudes de los lados / valores de los ángulos) para encontrar los otros valores de un triángulo rectángulo, por lo que es bastante útil.

Incluso puedes usar la naturaleza de "ciclismo" de las funciones seno y coseno para comportamientos especiales en un juego, por ejemplo, he visto que cos / sin se usa mucho para hacer que un objeto gire sobre otro.

Jesse Emond
fuente
8
Vale la pena señalar que Wikipedia describe otros usos para Atan2 ( no atan) que simplemente evitar la división por cero. Por ejemplo, se corrige solo para el cuadrante que se usa, donde normalmente tendría que hacer todo eso usted mismo.
doppelgreener
De hecho, una nota muy importante allí mismo. Actualizando mi respuesta.
Jesse Emond el
¿No te pusiste bronceado y atan hacia atrás en tu primer párrafo largo? Usaría atan para obtener el ángulo (es decir, invertir la ecuación) y broncear para obtener la relación de los lados (es decir, exactamente lo que dice la ecuación).
jhocking
Bueno, si sabes que o / a es igual a, por ejemplo, 3, entonces si quieres el ángulo que haces atan (3), eso es lo que quise decir: si quieres aislar el ángulo, usas atan en la relación. Si desea aislar la relación, use tan en el ángulo.
Jesse Emond el
Cambiaré tu redacción entonces, porque parece que estabas diciendo lo contrario.
jhocking
64

ingrese la descripción de la imagen aquí

Gareth Rees
fuente
1
¿Sería descortés editar la respuesta superior para tener este diagrama? Este diagrama es excelente y encajaría bien justo después de la explicación escrita de Jesse de atan2 ().
jhocking
1
Adelante: ¡sé mi invitado! Eliminaré esta respuesta después de que hayas terminado.
Gareth Rees
77
No no. ¡Seguid así! Se acredita y la gente aún debería votar a favor aquí por el diagrama.
Jesse Emond el
12

Aquí hay una forma ligeramente diferente de pensar acerca de las funciones trigonométricas, incluyendo atan () y atan2 (), que encuentro útil (las explicaciones en términos de "opuesto / adyacente" me confunden por alguna razón).

x, y, r, theta

Puede ir de un punto a otro moviendo las unidades x horizontalmente y las unidades y verticalmente (llamadas coordenadas rectangulares o cartesianas ) o moviendo la distancia r en un ángulo de Ɵ (llamadas coordenadas polares en 2D).

Digamos que tenemos una coordenada polar (r, Ɵ) y queremos convertirla a (x, y).

cos (Ɵ) te da la proporción de r que se encuentra a lo largo del eje x :

  • Si r = 1, entonces x = cos (Ɵ).
  • Si r = 100, entonces x = 100 * cos (Ɵ).
  • En general x = r * cos (Ɵ).

Del mismo modo, sin (Ɵ) te da la proporción de r que se encuentra a lo largo del eje y :

  • Si r = 1, entonces y = sin (Ɵ).
  • Si r = 100, entonces y = 100 pecado * (ɵ).
  • En general, y = r * sin (Ɵ).

¿Qué tal convertir coordenadas rectangulares (x, y) en coordenadas polares (r, Ɵ)?

r es la hipotenusa del triángulo rectángulo formado por x e y , entonces:

  • r = sqrt (x x + y y)

tan (Ɵ) da la pendiente, el aumento sobre la carrera, de la línea con longitud r . Entonces:

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

Sin embargo, al realizar y / x, calcular 3/4 da la misma respuesta que calcular -3 / -4. Del mismo modo, -3/4 da la misma respuesta que 3 / -4. Entonces tenemos atan2 (y, x) que maneja los signos individuales correctamente y evita un error de división por cero / infinito.

  • Ɵ = atan2 (y, x)
AbePralle
fuente
4

Jesse y Sid están básicamente en lo cierto, pero sospecho que realmente está buscando información sobre el problema.

Se necesita Atan2 () ya que atan () no le indica el ángulo desde la horizontal que necesita, ya que no hace frente a los cuadrantes.

Esto significa que usar atan para los vectores (-2,2) y (2, -2) dará el mismo valor. Luego, debe activar el signo de sus argumentos y agregar pi al resultado. Además, tiene el caso especial de dividir por cero para considerar que Jesse mencionó. También atan2 () funciona mejor que atan cuando x está cerca de 0

Entonces, si quieres el ángulo de un vector entre -pi y pi

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

o

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
fuente
1
"Esto significa que usar atan para los vectores (-2,2) y (2,2) dará el mismo valor". Si este es el caso, su atan está increíblemente roto, porque uno de ellos debería ser -π / 4 y el otro π / 4. Es una pena para todos los que votaron por esta basura.
El código aún está mal. Estás probando para y==0luego dividir por xen la otra rama.
sam hocevar
0

Aclararé algunas cosas de manera concisa. Consulte los tutoriales de trigonometría en línea para obtener una explicación detallada.

Deja que sea un ángulo. Entonces tan (a) = tan (a + 2 * pi).

atan es tan inverso, es decir, te da el ángulo dado el bronceado. Cuando llame a atan (tan (a + 2 * pi)), la respuesta será a. Esto será inadecuado para su aplicación.

atan2 tomará 2 argumentos para ayudar a estas situaciones exactas. atan toma x e y, que son básicamente cos (a) y sin (a).

atan2 (sin (a), cos (a)) = a atan2 (sin (a + 2 * pi), cos (a + 2 * pi)) = a + 2 * pi / * sin y cos tiene diferentes signos, lo que lleva a una respuesta diferente * /

Encuentre algunos tutoriales para explicar por qué es así.

Su código debería ser algo como esto:

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
fuente
tan(a) = - tan(-a), la ecuación que querías expresar fue quizástan(a) = tan(pi+a)
Ali1S232
0

Un uso atan2que encontré en mi código es "ángulo firmado".

Normalmente, la forma en que encontraría el ángulo entre dos vectores es

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

Pero esto no le dice cuál "guía" (es decir, está "más adelante en sentido horario" que el otro). Esta información puede ser importante para el seguimiento de gestos.

Puede encontrar el ángulo desde el eje x (1,0)para ambos vectores, pero existe este desagradable problema de ambigüedad: un vector con un ángulo de 315 grados devuelve 45 grados usando el cosmétodo anterior, y también lo hace un ángulo de 45 grados. Podrías hacer una comprobación de signos ypara arreglar eso, o podrías usar 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
fuente
0

Tenga en cuenta que atan no está roto. arctan o tan inversa es solo una función entre -PI / 2 y PI / 2. Repite este patrón, pero no es una función que sea un problema para una computadora, ya que no maneja múltiples respuestas.

Esto es lo mismo para asin entre -PI / 2 y PI / 2 y acos entre 0 y PI. Estos son los rangos más simples para que ocurra una función. Para atan y asin va de lo más negativo a lo más positivo. Porque acos va de lo más positivo a lo más negativo. (esto ayuda a interpolar respuestas más precisas)

asin, acos y atan son las funciones matemáticas.

Sin embargo, atan2 es mucho más útil para la programación, ya que proporciona la revolución completa (PI en radianes o 360 grados o 400 gradios). Tenga en cuenta que solo produjeron uno para bronceado, no para pecado o cos. Tan es el único que usa horizontal y vertical (x, y)

Dos
fuente