Поле зрения XNA в 2D

Я работаю над 2D-игрой в XNA, основанной на стекании. Я применил метод стаи Крейга Рейнольдса и теперь хочу динамически назначать лидера группе, чтобы направлять ее к цели.

Для этого я хочу найти игрового агента, перед которым нет других агентов, и сделать его лидером, но я не уверен в математике для этого.

В настоящее время у меня есть:

Vector2 separation = agentContext.Entity.Position - otherAgent.Entity.Position;

float angleToAgent = (float) Math.Atan2(separation.Y, separation.X);
float angleDifference = Math.Abs(agentContext.Entity.Rotation - angleToAgent);
bool isVisible = angleDifference >= 0 && angleDifference <= agentContext.ViewAngle;

agentContext.ViewAngle — это значения в радианах, с которыми я играл, чтобы попытаться получить правильный эффект, но в основном это приводит к тому, что все агенты назначаются лидерами.

Может ли кто-нибудь указать мне правильное направление, чтобы определить, находится ли объект в пределах «конуса» зрения другого объекта?


person Jason    schedule 09.11.2010    source источник
comment
angleDifference ›= 0 всегда верно, потому что angleDifference является результатом функции Abs.   -  person Empyrean    schedule 11.11.2010


Ответы (2)


Вам необходимо нормализовать входные данные для функции Atan2. Также вы должны быть осторожны при вычитании углов, потому что результат может быть за пределами диапазона от пи до -пи. Я предпочитаю использовать векторы направления, а не углы, поэтому вы можете использовать операцию скалярного произведения для такого рода вещей, поскольку это, как правило, быстрее, и вам не нужно беспокоиться об углах за пределами канонического диапазона.

Следующий код должен достичь результата, который вам нужен:

    double CanonizeAngle(double angle)
    {
        if (angle > Math.PI)
        {
            do
            {
                angle -= MathHelper.TwoPi;
            }
            while (angle > Math.PI);
        }
        else if (angle < -Math.PI)
        {
            do
            {
                angle += MathHelper.TwoPi;
            } while (angle < -Math.PI);
        }

        return angle;
    }

    double VectorToAngle(Vector2 vector)
    {
        Vector2 direction = Vector2.Normalize(vector);
        return Math.Atan2(direction.Y, direction.X);
    }

    bool IsPointWithinCone(Vector2 point, Vector2 conePosition, double coneAngle, double coneSize)
    {
        double toPoint = VectorToAngle(point - conePosition);
        double angleDifference = CanonizeAngle(coneAngle - toPoint);
        double halfConeSize = coneSize * 0.5f;

        return angleDifference >= -halfConeSize && angleDifference <= halfConeSize;
    }
person Empyrean    schedule 11.11.2010

Я думаю, вы хотите проверить +/- угол, а не только + (т.е. angleDifference >= -ViewAngle/2 && angleDifference <= ViewAngle/2). Или используйте абсолютное значение.

person jv42    schedule 09.11.2010