C# XNA 移动 - 可以转动或移动,但不能同时移动

C# XNA Movement - Can either turn or move, not both

我正在尝试制作一个 XNA 宇宙飞船游戏,我可以在其中转弯并开枪等。我 运行 遇到了一个问题,试图得到它,这样我就可以给一艘船一个航路点。出于某种原因,我可以让船移动,也可以让它转弯,但我似乎无法让它同时完成这两项操作。真是st运行ge.

基本上,如果我注释掉我的旋转代码,它会直线飞行,否则它会转弯,但它不会移动它只是停留在原地。

 if (GoToWayPoint == true)
 {

     //CurrentWayPoint.Normalize();
     Pos.Normalize();

     float angle = (float)Math.Atan2(CurrentWayPoint.X - Pos.X, CurrentWayPoint.Y - Pos.Y);

     //Rotate if 
     if (Rotation > angle && Rotation - TurnSpeed >= angle)
     {
         Rotation -= TurnSpeed;
     }
     else if (Rotation < angle && Rotation + TurnSpeed <= angle)
     {
         Rotation += TurnSpeed;
     }
     else
     {
         Rotation = angle;
     }

     //Move forward if it's facing the right direction
     if (Rotation == angle)
     {
         Velocity.X += (float)Math.Cos(Rotation) * TangentialVelocity * Speed;
         Velocity.Y += (float)Math.Sin(Rotation) * TangentialVelocity * Speed;
     }        

     if (Pos == CurrentWayPoint || Vector2.Distance(Pos,CurrentWayPoint) < 10)
     {
         Pos = CurrentWayPoint;

         GoToWayPoint = false;
     }

 }

 //Movement, player controlled
 if (PlayerControlled == true)
 {
     KeyboardState NewKey = Keyboard.GetState();

     //Move Up
     if (NewKey.IsKeyDown(Keys.Up) || NewKey.IsKeyDown(Keys.W))
     {
         Velocity.X = (float)Math.Cos(Rotation) * TangentialVelocity * Speed;
         Velocity.Y = (float)Math.Sin(Rotation) * TangentialVelocity * Speed;
     }

     //Move Down
     if (NewKey.IsKeyDown(Keys.Down) || NewKey.IsKeyDown(Keys.S))
     {
         Velocity.X = (float)Math.Cos(Rotation + Math.PI) * TangentialVelocity;
         Velocity.Y = (float)Math.Sin(Rotation + Math.PI) * TangentialVelocity;
     }

     //Move Right
     if (NewKey.IsKeyDown(Keys.Right) || NewKey.IsKeyDown(Keys.D))
     {
         Rotation += TurnSpeed;
     }

     //Move Left
     if (NewKey.IsKeyDown(Keys.Left) || NewKey.IsKeyDown(Keys.A))
     {
         Rotation -= TurnSpeed;
     }
}

//Update Movement
Pos += Velocity;

//Friction
float i = Velocity.X;
float j = Velocity.Y;

Velocity.X = i -= Friction * i;
Velocity.Y = j -= Friction * j;

此外,我有代码可以使用箭头键控制游戏对象。该代码工作正常,并使用相同类型的代码继续前进。

你的问题主要出在这一行:

if (Rotation == angle)

只有当该条件评估为 true 时,您的船才会前进。不幸的是,它永远不会是真的,因为角度是 float。除非您专门为它们分配相同的值,否则很难让两个浮点数彼此相等(还有其他方法,但在这种情况下它们无关紧要)。

你在这里计算angle

float angle = (float)Math.Atan2(CurrentWayPoint.X - Pos.X, CurrentWayPoint.Y - Pos.Y);

这很可能会给你一个小数点后有很多数字的值,比如 1.519573617...。最重要的是,你只是将你的船转向某个固定的量,TurnSpeed,这将总是跳过你的精确方向值,改变 angular 方向,然后再次跳过它,无限次。这就是为什么你永远不会前进。

我想到了两种解决方案,您可以尝试一下:

一个是丢掉上面的 if 语句。然后你的飞行器将开始前进,尽管方向错误,但它会在移动时调整方向。

另一种是用一个epsilon来比较Rotationangle。它看起来像这样:

if (Math.Abs(Rotation - angle) < epsilon)
{
    Rotation = angle;
    // move forward
}

这在比较浮点数时为您提供了一些回旋余地,即 epsilon 的回旋余地。它必须足够大,这样您的 TurnSpeed 就不会跳过整个间隔,但又要足够小,这样它就不会与确切的方向有太大的不同。

关键是你在使用旋转来移动和射击。更准确地说,你使用相同的角度进行拍摄和移动。

您有两个解决方案:

1,移动船只位置 up/down/left/right 而不使用角度。这意味着代码将类似于 if(<em>key up is pressed</em>) ship.position.Y -= ship.speed;。这意味着你解放了绘画和拍摄的角度。

2、为船创建新的角度变量。现在你有两个(假设 moveAngleshootAngle)。因此,当您移动船只时使用 moveAngle,当您需要计算射击位置时,使用 shootAngle。现在剩下的就是让您选择绘图的角度了。

奖励:使用左右键从船的方向扫射 90 度。