Поле зрения 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 - это значения в радианах, с которыми я играл, чтобы попытаться получить правильный эффект, но это в основном приводит к тому, что все агенты назначаются лидерами.
Может ли кто-нибудь указать мне правильное направление, чтобы определить, находится ли объект в "конусе" зрения другого объекта?
2 ответа
Вам необходимо нормализовать вход для функции Atan2. Также вы должны быть осторожны при вычитании углов, потому что результат может быть вне диапазона от пи до -pi. Я предпочитаю использовать векторы направления, а не углы, чтобы вы могли использовать операцию точечного произведения для такого рода вещей, поскольку это имеет тенденцию быть быстрее, и вам не нужно беспокоиться об углах за пределами канонического диапазона.
Следующий код должен достичь желаемого результата:
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;
}
Я думаю, что вы хотите проверить угол +/-, а не только + (т.е. angleDifference >= -ViewAngle/2 && angleDifference <= ViewAngle/2
). Или используйте абсолютное значение.