Математическая проблема ракетной системы (очень мало кода) - PullRequest
1 голос
/ 01 сентября 2011

Я хочу, чтобы Ракета следовала за игроком по следующим правилам:
- когда игрок находится справа от ракеты, измените вращение вправо с фиксированной скоростью
- иначеизмените вращение влево с той же скоростью

            if (missile.Rotation > 0 && missile.Rotation < Math.PI)
            {
                if (angle > missile.Rotation && angle < missile.Rotation + Math.PI)
                {
                    missile.Rotation += 0.05f;
                }
                else
                {
                    missile.Rotation -= 0.05f;
                }
            }
            else
            {
                if (angle < missile.Rotation && angle > missile.Rotation - Math.PI)
                {
                    missile.Rotation -= 0.05f;
                }
                else
                {
                    missile.Rotation += 0.05f;
                }
            }  
            missile.Position += new Vector2((float)(5 * gameTime.ElapsedGameTime.TotalSeconds * Math.Cos(missile.Rotation)), (float)(5 * gameTime.ElapsedGameTime.TotalSeconds * Math.Sin(missile.Rotation)));

С этим кодом, кажется, что некоторые ракеты дают ошибку, когда я прыгаю с игроком, ракеты идут в бесконечный цикл, который невозможно остановить(они летят по кругу)

система координат похожа на XNA (360/0 ° справа, 270 ° сверху ...)

кто-нибудь может мне помочь?

1 Ответ

7 голосов
/ 01 сентября 2011

Использование углов Эйлера - очень неэффективный способ сделать это. Гораздо проще использовать векторы.

Пусть P - позиция игрока, а M - позиция ракеты. Из них нужно рассчитать два вектора: MP и Mr, где MP = вектор от ракеты к игроку, а Mr - вектор, указывающий на правую сторону ракеты. Теперь вычислите скалярное произведение между векторами MP и Mr. Знак результата говорит вам, каким способом повернуть ракету. Если оно положительное, поверните ракету по часовой стрелке, если отрицательно, то поверните ракету против часовой стрелки.

Почему это работает?

Точечное произведение двух векторов A и B можно записать в виде:

Ax.Bx + Ay.By

, а также:

|A|.|B|.cos (theta)

где тета - угол между двумя векторами и | x | это величина вектора х. Это дает нам:

cos (theta) = (Ax.Bx + Ay.By) / (|A|.|B|)

Поскольку мы хотим знать только знак значения cos (theta), положительные значения - это углы между + - 90 градусов, а отрицательные значения - это углы между 90 и 270 градусами, нам нужно только определить знак числителя. знаменатель всегда положительный! Таким образом, знак точечного произведения скажет нам, на какой стороне находится цель.

Но вы думаете, разве векторы не труднее использовать, чем углы? Не нужно ли мне сделать несколько триггерных функций для вычисления правильного вектора ракеты?

В идеале, вы не должны использовать углы Эйлера вообще ни для чего. Вы должны использовать матрицы для хранения положения и поворота объектов в вашем мире. Правый вектор ракеты - это только верхний ряд матрицы положения / ориентации ракеты (или первый столбец, зависит от того, как вы настроили свою систему). А матрицы - это то, что аппаратное обеспечение рендеринга использует для рисования объектов, поэтому вы не добавляете какие-либо накладные расходы, используя их (на самом деле, использование углов добавляет накладные расходы, так как обозначение угла необходимо преобразовать в матрицы для рендеринга).

РЕДАКТИРОВАТЬ: Ваш код должен выглядеть так:

if (VectorDotProduct (missile.right, player.pos - missil.pos) > 0)
{
   missile.rotate clockwise
}
else
{
   missile.rotate anti-clockwise
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...