【问题标题】:Figuring out which direction my object is facing on a 2D plane?弄清楚我的对象在 2D 平面上朝向哪个方向?
【发布时间】:2013-01-28 14:18:32
【问题描述】:

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

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

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

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

【问题讨论】:

  • 考虑使用 2d 向量跟踪运动,即 [3,4] 可能意味着在任何给定的秒内,一个对象将垂直移动 3 个单位,水平移动 4 个单位(=5 个单位 @ ~35度)
  • 请务必在gamedev 上发布此内容。
  • 感谢大家的建议! stackoverflow 永远不会失败!!!!

标签: c# xna 2d game-physics


【解决方案1】:

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

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

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

我关于这个问题的代码的 Asn-ps:

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();
  }
}

【讨论】:

    【解决方案2】:

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

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

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

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

    【讨论】:

      【解决方案3】:

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

      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);
      }
      

      【讨论】:

      • 魔术师,你如何将双精度加到向量/点上?你的意思是:(位置+距离)*方向;或位置+(距离*方向); ?
      • 后者,我有点无聊,所以我在代码中编写了一些假人。希望我做对了:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-10-21
      • 2019-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-05
      • 1970-01-01
      相关资源
      最近更新 更多