我正在用 XNA 开发一个基于集群行为的 2D 游戏。我已经实现了 Craig Reynold 的集群技术,现在我想动态地为群体分配一个领导者,以引导它朝着目标前进。
为了做到这一点,我想找到一个前方没有任何其他游戏代理的代理,并使其成为领导者,但我不确定这方面的数学原理。
目前我有:
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 是一个弧度值,我一直在尝试使用它来获得正确的效果,但这通常会导致所有代理都被分配为领导者。
谁能指出正确的方向,以检测一个实体是否在另一个实体的“视野锥”内?
回答:
你需要将 Atan2 函数的输入标准化。此外,当减去角度时,你必须小心,因为结果可能超出 pi 到 -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; }