0

我正在寻找更好的方法来计算一个对象是面向另一个对象还是一个对象在另一个对象后面。到目前为止,我已经能够创建它,但它似乎不能 100% 正确工作:(

我也认为它应该是弧度而不是度数。

public static float GetAngle(float x1, float y1, float x2, float y2)
{
    float xDiff = x2 - x1;
    float yDiff = y2 - y1;
    var angle = RadianToDegree((float)Math.Atan2(yDiff, xDiff));

    if (angle < 0)
        return 360 + angle;

        return angle;
    }

public static bool IsFacing(Point obj, float rotationAngle, Point target, float arcDegree = 180)
{
    var angleBetweenPoints = GetAngle(obj, target);

    return rotationAngle >= angleBetweenPoints - arcDegree / 2 && rotationAngle <= angleBetweenPoints + arcDegree / 2;
}

public static bool IsBehind(Point obj, float rotationAngle, Point target, float arcDegree = 180)
{
    var angleBetweenPoints = GetAngle(obj, target);
    var backViewAngle = rotationAngle > 180 ? rotationAngle - 180 : 180 - rotationAngle;
    return backViewAngle >= angleBetweenPoints - arcDegree / 2 && backViewAngle <= angleBetweenPoints + arcDegree / 2;
}
4

1 回答 1

0

乍一看,您的问题似乎出在方法中的rotationAnglevs测试中。angleBetweenPointsIsFacing()

鉴于:

rotationAngle = 0, angleBetweenPoints = 350, arcDegree = 180

那么测试将是:

test = 0 >= (350 - 180 / 2) && 0 <= (350 + 180 / 2)
     = 0 >= 260 && 0 <= 440
     = false

这会经常发生,这是由于您的角度使用了范围 [0..360]。虽然这在某些情况下很有用,但这不是其中一种情况。这里更有用的是在 [-180..180] 范围内获得航向角和目标角的差异,然后比较arcDegree变得简单得多。

尝试这个:

// Adjust a value to fit in the specified range
public static float Clamp(float v, float low, float high)
{
    float range = high - low;
    float modifier = ((int)((v - low) / range) - (v < low ? 1 : 0)) * range;
    v -= modifier;
    return v;
}

// Get the angle between a point+heading and another point
// Returns an angle in the range (-180..180) where:
//  res < 0     target clockwise from heading
//  res == 0    target at heading
//  res > 0     target counter-clockwise from heading
static float RelativeAngle(float heading, float x1, float y1, float x2, float y2)
{
    // get angle between points in world coordinates
    float angle = RadianToDegree((float)Math.Atan2(y2 - y1, x2 - x1));
    // adjust to local coordinates and normalize
    return Clamp(angle - heading, -180, 180);
}

public static bool IsFacing(Point obj, float rotationAngle, Point target, float arcDegree = 180)
{
    var angleBetweenPoints = RelativeAngle(rotationAngle, obj.x, obj.y, target.x, target.y);
    return angleBetweenPoints >= -(arcDegree / 2) && angleBetweenPoints <= (arcDegre / 2);
}
于 2013-02-15T03:15:01.677 回答