我在 XNA 中制作游戏。我有敌人和玩家。敌人应该逐渐转向玩家。他们应该确定是否需要顺时针或逆时针转动,以较短者为准。
通过使用 Atan2,我得到了敌人当前面对的角度和它应该面对的角度(敌人和玩家之间的线的角度)作为弧度。
我得到了一些奇怪的行为。让我们在下面的场景中说。敌人可能会完全转向错误的方向。
我的代码(如下)越来越长,但我仍然遇到问题。这段代码是敌人类更新方法的一部分。这一定是游戏中需要克服的常见问题。有没有办法解决这个问题?
//this bit is just in case enemy has rotated more than 360 degrees (gets set back to 0)
if (Math.Abs(_blocklist[0]._floor.Revolutions) >= 2)
{
_blocklist[0]._floor.Rotation = 0.0f;
}
//enemy rotation in radians
float blockroat = _blocklist[0]._floor.Rotation;
// vector to player - vector to enemy
_vectToPlayer = playerpos - _blocklist[0].Centre
angletoplayer = (float)(Math.Atan2(_vectToPlayer.Y, _vectToPlayer.X));
diff = blockroat - angletoplayer;
if (diff < -Math.PI)
{
diff += (float) Math.PI;
diff = -diff;
}
else if (diff > Math.PI)
{
diff -= (float)Math.PI;
diff = -diff;
}
// if enemy angle if off by a certain amount
if (Math.Abs(diff) >_maxturn)
{
if (diff < 0)
{
//turn clockwise
_blocklist[0]._floor.Rotation += _maxturn;
}
else
{
//turn anti clockwise
_blocklist[0]._floor.Rotation -= _maxturn;
}
}
更新
我最终使用了这样的方法 2.. 效果很好。它也比我以前的代码整洁得多
//enemy rotation in radians from farseer (red line)
float brot = _blocklist[0]._floor.Rotation + ((float)Math.PI/2);
//vector from enemy to player (blue line)
Vector2 _vectToPlayer = playerpos - _blocklist[0].Centre;
//cross product of 2d vectors
cross = (_vectToPlayer.X * (float)Math.Sin(brot)) - ((float)Math.Cos(brot) * _vectToPlayer.Y);
//tolerance for how closely enemy must point towards player
if (Math.Abs(cross) > 5)
{
if (cross > 0)
{
//turn anticlockwise
_blocklist[0]._floor.Rotation -= _npcstats.maxturnspeed;
}
else
{
//turn clockwise
_blocklist[0]._floor.Rotation += _npcstats.maxturnspeed;
}
}
我认为我以前的代码或多或少完全按照建议的方法 1。但我无法让它工作。我把它归结为 Farseers 坐标系的变幻莫测 + 它如何与我自己的交互。