Подтвердить что ты не робот

Как постепенно поворачивать объект к другому, поворачивая кратчайшее расстояние

В настоящее время я пытаюсь повернуть спрайт в зависимости от того, сколько градусов (или рад, я предпочитаю градусов), оно отличается от прямой к цели, проблема в том, когда цель достигает определенной позиции, спрайты решают сделать поворот полный 360 на другой способ вместо того, чтобы делать 10 дополнительных. Эта картина, вероятно, лучше объясняет проблему:

Blue square = target, Red square = the object, green line = rotation it wants, black line = current rotation, brown arrow = how it rotates to achieve this, red arrow = how I want it to rotate.

Синий квадрат = цель

Красный квадрат = объект

Зеленая линия = вращение, которое он хочет

Черная линия = текущее вращение

Браун arrow = как он вращается для достижения этого

Красная стрелка = как я хочу, чтобы она вращалась.

Обратите внимание, что случай 1 всегда работает, в зависимости от того, как он вращается, но в случае 2 он всегда делает это вращение, независимо от того, принадлежит ли оно "правым" или "левым" текущего вращения.

Это код, который я использую для поворота объекта.

    Vector2 distance = new Vector2(target.worldPos.X - this.worldPos.X, target.worldPos.Y - this.worldPos.Y);
    float wantRot = (float)Math.Atan2(distance.Y, distance.X);
    if (this.rotation < wantRot)
        this.rotation += MathHelper.ToRadians(45) * Time.deltaTime;
    if (this.rotation > wantRot)
        this.rotation -= MathHelper.ToRadians(45) * Time.deltaTime;

Чего я хочу добиться - поверните его (в случае 2) в соответствии с красной стрелкой, а не коричневой.

ЗАМЕЧАНИЕ: Я не специалист по программированию, я делал это только время от времени в течение прошлого года (в основном простой 2D-шутер/shoot'em вверх по виду игр), поэтому в подробном объяснении будет оценено, Я также участвую в обучении программированию.

PS: Предложения по титулу также будут оценены, поскольку я не имел абсолютно никакого представления о том, что там делать.

4b9b3361

Ответ 1

Ваша проблема в том, что цель может быть под углом 5, и объект может быть обращен к 355 градусам (например). Согласно вашему тесту, 5 меньше 355, поэтому идите против часовой стрелки.

Что вам нужно сделать, это проверить, находится ли цель в пределах 180 градусов влево или в пределах 180 градусов вправо, а затем двигаться соответственно.

Сложная часть получает проверку, чтобы "обернуть" вокруг 360 ↔ 0. Похоже, что в вашем случае осталось 0 градусов, поэтому жесткий тест выполняется, когда wantRot находится сбоку, которая имеет 0 градусов внутри него.

Чтобы визуализировать кружок, как показано ниже, поместите объект слева от того, с которым мы сталкиваемся. Вы увидите, что вам нужно отдельно проверить две затененные области.

Visualisation

Метод 1

Проверить все случаи отдельно.

Примечание. Код ниже в моей голове и не проверен. Вам нужно будет изменить градусы на радианы.

int MoveDir = 0;
var BehindMe = this.rotation - 180;
if (BehindMe < 0)
    BehindMe += 360;

if (wantRot != this.rotation)
{
    if (wantRot == BehindMe)
        MoveDir = 1; // or randomly choose
    else if ((wantRot > BehindMe && wantRot < this.rotation) ||
             (this.rotation < 180 && (wantRot > BehindMe ||
                                      wantRot < this.rotation)))
        MoveDir = -1;
    else if ((wantRot < BehindMe && wantRot > this.rotation) ||
             (this.rotation > 180 && (wantRot < BehindMe ||
                                      wantRot > this.rotation))
        MoveDir= 1;

    this.rotation += MoveDir * MathHelper.ToRadians(45) * Time.deltaTime;
}

Метод 2

От взгляда на изображение вы можете понять, что вы можете просто проверить, стоит ли объект справа, а если нет, считать его слева (поскольку до тех пор, пока текущий угол меньше 180 градусов, проверка его на право легко). Если текущий угол составляет более 180 градусов, тогда отмените концепцию - проверьте, стоит ли она слева, а если не предполагать права. Что-то вроде ниже:

int MoveDir = 0;
var BehindMe = this.rotation - 180;
if (BehindMe < 0)
    BehindMe += 360;

if (wantRot != this.rotation)
{
    if (this.rotation <= 180)
    {
        if (wantRot > this.rotation && wanrRot < BehindMe)
            MoveDir = 1;
        else
            MoveDir = -1;
    }
    else
    {
        if (wantRot < this.rotation && wanrRot > BehindMe)
            MoveDir = -1;
        else
            MoveDir = 1;
    }

    this.rotation += MoveDir * MathHelper.ToRadians(45) * Time.deltaTime;
}