1

我和我的朋友在 XNA 4.0 中玩弄 2D 赛车游戏。有点像这个:Ivan “Ironman” Stewart 的 Super Off Road。我们遇到的问题是知道汽车面向哪个方向以适当地移动它。我们可以通过枚举值 North、South、East、West 来跟踪方向,但出于多种原因我们不想这样做。

我们想知道是否有办法通过数学来实现这一点。也许通过在汽车引擎盖上指定一个锚点并让汽车始终朝着该位置移动,然后移动该锚点。我们不确定。或者也许有一种使用二维向量的方法。

我想既然我们遇到了困难,我们应该向编码社区寻求帮助!

只是要清楚。我不是在寻找代码;我只想讨论所有方向的 2D 运动的一些概念,而不必跟踪方向枚举。我知道这不是唯一的方法。

4

3 回答 3

1

汽车物理实际上是一门非常难的学科。我祝你一切顺利,但你正在着手一项艰巨的任务。

至于答案:您可以将方向角存储为弧度并使用 atan2 函数来获取角度之间的关系。

或者您可以使用 Vector2D 并使用矢量数学来确定角度,atan2 也将成为您的朋友。

我在这个问题上的代码片段:

public class RotatingImage implements RotatingImageVO {
  protected double x, y; // center position
  protected double facingx, facingy;
  protected double angle;

  protected void calculateAngle() {
    angle = Math.atan2(x-facingx, facingy-y);
  }
}

请记住,计算 atan2 的成本很高。当我为每个对象(塔防,塔在旋转;)的每次绘制迭代中执行此操作时,它占用了我大约 30% 的计算能力。只有在检测到明显的角度变化时才这样做。像这样:

public void setFacingPoint(double facingx, double facingy) {
  if (Math.abs((facingx-this.facingx)/(facingx+this.facingx)) > 0.002 
      || Math.abs((facingy-this.facingy)/(facingy+this.facingy)) > 0.002) {
    this.facingx = facingx;
    this.facingy = facingy;
    calculateAngle();
  }
}
于 2013-01-28T14:22:29.273 回答
0

使用单位向量描述方向和使用点描述位置是有意义的。然后当汽车向前移动时

currentPosition = currentPosition + distance * directionvector;//(伪代码)

改变方向时,最好使用矩阵来(旋转)变换方向向量。

(我对 XNA 不熟悉)

写了一些虚拟代码来说明:

[Test]
public void MoveForwardTest()
{
    var position = new Point(0, 0);
    var direction = new Vector(1, 0);
    double distance = 5;
    //Update position moving forward distance along direction
    position = position + distance * direction; 
    Assert.AreEqual(5.0, position.X, 1e-3);
    Assert.AreEqual(0, position.Y, 1e-3);
}

[Test]
public void RotateThenMoveTest()
{
    var position = new Point(0, 0);
    var direction = new Vector(1, 0);
    double distance = 5;
    //Create the rotation matrix
    var rotateTransform = new RotateTransform(90); 
    //Apply the rotation to the direction
    direction = Vector.Multiply(direction, rotateTransform.Value); 
    //Update position moving forward distance along direction
    position = position + distance * direction; 
    Assert.AreEqual(0, position.X, 1e-3);
    Assert.AreEqual(5.0, position.Y, 1e-3);
}

[Test]
public void CheckIfOtherCarIsInfrontTest()
{
    var position = new Point(0, 0);
    var direction = new Vector(1, 0);
    var otherCarPosition = new Point(1, 0);
    //Create a vector from current car to other car
    Vector vectorTo = Point.Subtract(otherCarPosition, position); 
    //If the dotproduct is > 0 the other car is in front
    Assert.IsTrue(Vector.Multiply(direction, vectorTo) > 0); 
}

[Test]
public void AngleToNortTest()
{
    var direction = new Vector(1, 0);
    var northDirection = new Vector(0, 1);
    Assert.AreEqual(90, Vector.AngleBetween(direction, northDirection), 1e-3);
}
于 2013-01-28T14:27:18.990 回答
0

您可以使用归一化向量来表示方向。这只是一个硬编码示例,但您可以轻松地使用来自游戏手柄拇指杆的输入。

Vector2 north = new Vector2(0, -1);

然后在你的代码中像这样移动你的精灵(假设有一个位置向量)。

float speed = 100; // 100 pixels per second.
Vector2 direction = north;
position += direction * ((float)gameTime.ElapsedGameTime.TotalSeconds * speed);
于 2013-01-28T14:28:02.157 回答