Для чего используются atan и atan2 в играх?

48

У меня возникли проблемы с пониманием Math.tan()и Math.atan()и Math.atan2().

У меня есть базовые знания по тригонометрии, но использование SIN, COS, TAN и т. Д. Для разработки игр является для меня совсем новым.

Я читаю некоторые учебные пособия и вижу, что, используя тангенс, мы можем получить угол, на который нужно повернуть один объект, на сколько на него обращено другое лицо, например, моя мышь. Так почему же нам все еще нужно использовать atan или atan2?

sutoL
источник
Атан используется для определения угла, полезного для тысячи разных вещей. У вас есть актуальный вопрос о его использовании, или вы просто ищете общую математическую помощь?
BlueRaja - Дэнни Пфлюгофт
5
Вы определенно должны понимать математику / геометрию, стоящую за этими функциями; как только вы овладеете ими, они станут частью вашего «понимания мира», как базовая грамматика, которую вы используете каждый день, чтобы говорить. Как только вы сможете «говорить по математике / геометрии», вы увидите, что эти функции являются простыми инструментами для достижения результата, наиболее естественными для использования.
FxIII
Эти уроки либо ошибочны, либо вы их неправильно поняли. Вы используете atan2 (), чтобы получить угол от одного объекта к другому. Как это работает, объясняется ниже.
Джокинг
спасибо людям за ответы, теперь я
сожалею

Ответы:

94

Касательная формула такова:

tan(angle) = opposite/adjacent

Обратитесь к этому рисунку:

Диаграмма прямоугольного треугольника с обозначением угла тета и отмечены его противоположные и смежные стороны

Где aсоседняя сторона, oэто противоположная сторона и thetaэто угол. Аналогично, синус и косинус - это sin (ang) = o / h, а cos (ang) = a / h где hдлинная сторона: http://www.mathwords.com/s/sohcahtoa.htm

Между тем atan(сокращение от арктангенса , также известного как обратный тангенс ) является обратным tan, примерно так:

atan(opposite/adjacent) = angle

Таким образом, если вы знаете значения как противоположных, так и соседних сторон (например, вычитая координаты объекта из координат мыши), вы можете получить значение угла с помощью atan.

Однако в разработке игр может случиться так, что соседняя сторона равна 0 (например, координата x вектора равна 0). Помните, что tan(angle) = opposite/adjacentвероятность катастрофической ошибки деления на ноль должна быть очевидной. Так много библиотек предлагают функцию с именем atan2, которая позволяет определить как xи yпараметры, чтобы избежать деления на ноль для вас и дать угол в правом квадранте.

диаграмма atan2

(диаграмма любезно предоставлена ​​Гаретом, пожалуйста, проголосуйте и за его ответ)


Использование тригонометрии в разработке игр довольно распространено, особенно с векторами, но обычно библиотеки скрывают работу тригонометрии для вас. Вы можете использовать sin / cos / tan для множества задач, которые включают геометрические манипуляции, чтобы найти значение из треугольника. Все, что вам нужно, это 3 значения (длина стороны / угловые значения), чтобы найти другие значения прямоугольного треугольника, так что это весьма полезно.

Вы даже можете использовать "циклическую" природу функций синуса и косинуса для особого поведения в игре, например, я видел, как cos / sin много использовал, чтобы объект поворачивался вокруг другого.

Джесси Эмонд
источник
8
Стоит отметить, что Википедия описывает другие способы использования Atan2 ( не atan), кроме простого исключения деления на ноль. Например, он корректирует себя в соответствии с используемым квадрантом, где обычно вам придется делать все это самостоятельно.
двойник
Действительно, очень важная заметка тут же. Обновление моего ответа.
Джесси Эмонд
Разве ты не загорел и не атан задом наперед в своем первом длинном абзаце? Вы бы использовали atan, чтобы получить угол (т.е. перевернуть уравнение) и tan, чтобы получить соотношение сторон (то есть точно то, что говорит уравнение).
Джокинг
Хорошо, если вы знаете, что o / a равно, например, 3, тогда, если вы хотите угол, который вы делаете atan (3), это то, что я имел в виду: если вы хотите выделить угол, вы используете atan в отношении. Если вы хотите выделить соотношение, используйте угол наклона.
Джесси Эмонд
Тогда я изменю вашу формулировку, потому что звучит так, будто вы говорили обратное.
Джокинг
64

введите описание изображения здесь

Гарет Рис
источник
1
Было бы невежливо редактировать верхний ответ, чтобы иметь эту диаграмму в нем? Эта диаграмма великолепна и хорошо подходит сразу после письменного объяснения Джесси atan2 ().
Джокинг
1
Давай, будь моим гостем! Я удалю этот ответ после того, как вы закончите.
Гарет Рис
7
Нет нет. Так держать! Это зачислено, и люди все еще должны проголосовать здесь за диаграмму.
Джесси Эмонд
12

Вот немного другой способ мышления о функциях триггера - включая atan () и atan2 () - который я считаю полезным (объяснения в терминах «противоположный / смежный» просто почему-то меня смущают).

х, у, т, тета

Вы можете добраться из одной точки в другую, перемещая x единиц по горизонтали и y единиц по вертикали (так называемые прямоугольные или декартовы координаты) или перемещая расстояние r под углом Ɵ (так называемые полярные координаты в 2D).

Скажем, у нас есть полярная координата (r, Ɵ), и мы хотим преобразовать ее в (x, y).

cos (Ɵ) дает вам пропорцию r, которая лежит вдоль оси x :

  • Если r = 1, то x = cos (Ɵ).
  • Если r = 100, то x = 100 * cos (Ɵ).
  • В общем случае x = r * cos (Ɵ).

Аналогично, грех (Ɵ) дает вам пропорцию r, которая лежит вдоль оси y :

  • Если r = 1, то y = sin (Ɵ).
  • Если r = 100, то y = 100 * sin (Ɵ).
  • В общем, у = г * грех (Ɵ).

Как насчет преобразования прямоугольной координаты (x, y) в полярную координату (r, Ɵ)?

r - гипотенуза прямоугольного треугольника, образованного x и y , поэтому:

  • r = sqrt (x x + y y)

tan (Ɵ) задает наклон - подъем над трассой - линии длиной r . Так:

  • tan (Ɵ) = y / x
  • At = атан (у / х)

Однако при выполнении y / x вычисление 3/4 дает тот же ответ, что и вычисление -3 / -4. Аналогично -3/4 дает тот же ответ, что и 3 / -4. Таким образом, у нас есть atan2 (y, x), который правильно обрабатывает отдельные знаки и предотвращает ошибку деления на ноль / бесконечность.

  • Ɵ = atan2 (у, х)
AbePralle
источник
4

Джесси и Сид в основном правы, но я подозреваю, что вы действительно разбираетесь в проблеме.

Atan2 () необходим, так как atan () не говорит вам угол от горизонтали, который вам нужен, поскольку он не справляется с квадрантами.

Это означает, что использование atan для векторов (-2,2) и (2, -2) даст одинаковое значение. Затем вы должны включить знак ваших аргументов и добавить пи к результату. Кроме того, у вас есть особый случай деления на ноль, чтобы учесть, что упоминал Джесси. Также atan2 () работает лучше, чем atan, когда x близко к 0

Так что вы, если вы хотите угол вектора между -pi и пи

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

или же

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
источник
1
«Это означает, что использование atan для векторов (-2,2) и (2,2) даст одинаковое значение». Если это так, ваш атан невероятно сломан, потому что один из них должен быть -π / 4, а другой π / 4. Позор всем, кто проголосовал за эту фигню.
Код все еще не прав. Вы тестируете на y==0то, чтобы потом делиться xна другую ветку.
Сэм Хоцевар
0

Я поясню несколько вещей в сжатой форме. Пожалуйста, обратитесь к учебным пособиям по тригонометрии для подробного объяснения.

Позвольте быть угол. Тогда tan (a) = tan (a + 2 * pi).

atan - обратный загар, то есть дает угол, заданный загаром. Когда вы звоните atan (tan (a + 2 * pi)), ответ будет a. Это будет недостаточно для вашего приложения.

atan2 примет 2 аргумента, чтобы помочь этим точным ситуациям. atan принимает x и y, которые в основном являются cos (a) и sin (a).

atan2 (sin (a), cos (a)) = aan2 (sin (a + 2 * pi), cos (a + 2 * pi)) = a + 2 * pi / * sin и cos имеет разные знаки, ведущие на другой ответ * /

Пожалуйста, найдите некоторые учебники, чтобы объяснить, почему это так.

Ваш код должен быть примерно таким:

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), уравнение, которое вы хотели выразить, было возможноtan(a) = tan(pi+a)
Ali1S232
0

Одно из применений, которое atan2я нашел в своем коде, - «угол со знаком».

Обычно способ нахождения угла между двумя векторами

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

Но это не говорит вам, какой из них «ведет» (т. Е. Находится «дальше вперед по часовой стрелке», чем другой). Эта информация может быть важна для отслеживания жестов.

Вы можете найти угол от оси x (1,0)для обоих векторов, но есть одна неприятная проблема неоднозначности: вектор с углом 315 градусов возвращает 45 градусов, используя cosметод, описанный выше, и угол 45 градусов. Вы можете сделать проверку подписи, 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
источник
0

Обратите внимание, что Атан не сломан. обратное arctan или tan является функцией только между -PI / 2 и PI / 2. Он повторяет этот шаблон, но тогда это не та функция, которая является проблемой для компьютера, поскольку он не обрабатывает несколько ответов.

Это то же самое, что и между -PI / 2 и PI / 2 и acos между 0 и PI. Это самые простые диапазоны для возникновения функции. Для атана и асина он идет от самого негативного к самому позитивному. Для acos это идет от его самого положительного до его самого отрицательного. (это помогает в интерполяции более точных ответов)

так asin, acos и atan - математические функции.

atan2, однако, гораздо более полезен для программирования, поскольку обеспечивает полный оборот (PI в радианах или 360 градусах или 400 градусах). Обратите внимание, что они произвели только один загар, а не грех или соз. Tan - единственный, который использует горизонтальный и вертикальный (x, y)

двойка
источник