0

我有一个通过旋转移动的玩家精灵,它的旋转不断变化,但我还需要确定目标是在它的左侧还是右侧,而不是在前后旋转的 45 度范围内。

我已经编写了这段代码,我认为它应该可以工作,但它似乎只是偶尔拿起一侧,而另一侧则稍微多一些。

        public void GrappleCheck(AsteroidSprite target)
    {
        float targetTragectory = (float)Math.Atan2(Position.Y - target.Position.Y, Position.X - target.Position.X);

        if (targetTragectory < 0)
            targetTragectory += (float)(Math.PI * 2);

        if (Rotation < 0)
            Rotation += (float)(Math.PI * 2);

        if ((targetTragectory > Rotation + (float)(MathHelper.PiOver4 / 2)) && (targetTragectory < Rotation + (float)(Math.PI - (MathHelper.PiOver4 / 2))))
        {
            target.Distance = Vector2.Distance(Position, target.Position);
            if (RightTarget != null)
            {
                if (RightTarget.Distance > target.Distance)
                {
                    RightTarget.isTarget = false;
                    RightTarget = target;
                    RightTarget.ColorTint = Color.Blue;
                    RightTarget.isTarget = true;
                }
            }
            else
            {
                RightTarget = target;
                RightTarget.ColorTint = Color.Blue;
                RightTarget.isTarget = true;
            }
        }
        else if ((targetTragectory < Rotation - (float)(MathHelper.PiOver4 / 2)) && (targetTragectory > Rotation - (float)(Math.PI - (MathHelper.PiOver4 / 2))))
        {
            target.Distance = Vector2.Distance(Position, target.Position);
            if (LeftTarget != null)
            {
                if (LeftTarget.Distance > target.Distance)
                {
                    LeftTarget.isTarget = false;
                    LeftTarget = target;
                    LeftTarget.ColorTint = Color.Red;
                    LeftTarget.isTarget = true;
                }
            }
            else
            {
                LeftTarget = target;
                LeftTarget.ColorTint = Color.Red;
                LeftTarget.isTarget = true;
            }
        }
        else
        {
            target.isTarget = false;
        }

        if (controlInput.IsHeld(Keys.X))
        {
            Speed = Speed;
        }
4

2 回答 2

1

使用角度可能会很烦人。以下是一些不使用角度来解决问题的方法:

首先,我们需要到目标的方向和运动方向:

var targetDirection = target.Positon - Position;
// Update this to match the actual direction. The following line assumes that
// a rotation of 0 results in the right direction.
var movementDirection = new Vector2((float)Math.Cos(Rotation), (float)Math.Sin(Rotation));

您要解决的第一个问题是确定目标是否在 45° 圆锥内。您可以使用以下公式计算实际角度:

var dot = Vector2.Dot(myDirection, targetDirection);
//if dot is negative, then target is behind me, so just use the absolute value
var cos = Math.Abs(dot) / myDirection.Length() / targetDirection.Length();
var angle = Math.Acos(cos);
if(angle < MathHelper.PiOver4 / 2) //45° opening angle
    ; // within cone
else
    ; // outside cone

您的第二个问题是确定目标是在左侧还是右侧。为此,我们使用正交myDirection并指向左侧的向量:

//assuming that +x is the right axis and +y is the down axis
var normal = new Vector2(myDirection.Y, -myDirection.X);
dot = Vector2.Dot(normal, targetDirection);
if(dot > 0)
    ; // target is on the left side
else
    ; // target is on the right side

我希望这能让你的代码更容易更容易理解。您应该考虑在单独的方法中提取一些代码以使其更具可读性。

于 2013-02-10T15:56:15.633 回答
0

好的,我已经解决了,玩家轮换可以从 0 到 2 x PI + 或 -,保持它 + 虽然我输入

if (Rotation < 0)
    Rotation += (float)Math.PI * 2;

到目标的旋转可以是 0-PI 或 0 - 负 PI,具体取决于您声明 atan2 的方式和玩家所在的位置。

//This works out the difference from the targets rotation to the players rotation.

RotationDif = TargetRotation - PlayerRotation;

//If the difference is greater than PI then when we check to see if its is within
//the range 0-PI or 0-Negative PI it will be missed whilst still possibly being on 
//either side of the player, adding PI * 2 to the targets rotation basically spins
//it past the player so the Difference will be the shortest angle.

if(Math.Abs(RotationDif) > Math.PI)
   RotationDif = TargetRotation + (float)(Math.PI * 2) - PlayerRotation;

//Next we check to see if the target is left(negative) or
//the right(positive), the negative/positive assignment will depend
//on which way round you did the atan2 to get the target rotation.

if ((RotationDif > 0) && (RotationDif < (float)Math.PI))

    //Insert right target code here

else if ((RotationDif < 0) && (RotationDif > -(float)Math.PI))

    //Insert left target code here

else

    //Insert no target code here to cover all basis

就是这样,我制作了不同的 If (RotationDif > 0) 等,因此通过制作它来忽略前后 45 度角

If ((RotationDif > (float)(Math.PI / 8) &&
    (RotationDif < (float)(Math.PI - (Math.PI / 8)))

而另一方则相反,希望这对其他人有所帮助,因为我花了将近 2 周的时间来锻炼:/

于 2013-02-12T22:35:54.520 回答