弄清楚我的物体在2D平面上面向哪个方向?

时间:2013-01-28 14:18:32

标签: c# xna 2d game-physics

我的朋友和我在XNA 4.0中搞乱制作2D赛车游戏。有点像这样:伊万“铁人”斯图尔特的超级越野。我们遇到的问题是知道汽车正朝着哪个方向移动它。我们可以通过枚举值来追踪北方,南方,东方,西方的方向,但出于多种原因我们不想这样做。

我们想知道是否有办法通过数学来实现这一目标。也许通过在汽车引擎盖上指定一个定位点并使汽车始终朝向该位置移动然后移动该定位点。我们不确定。或者可能有使用2D矢量的方法。

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

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

3 个答案:

答案 0 :(得分: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();
  }
}

答案 1 :(得分: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);
}

答案 2 :(得分:0)

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

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

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

float speed = 100; // 100 pixels per second.
Vector2 direction = north;
position += direction * ((float)gameTime.ElapsedGameTime.TotalSeconds * speed);