【问题标题】:Determining direction of 2D vector with 8 discrete directions (horizontal, vertical and diagonals)确定具有 8 个离散方向(水平、垂直和对角线)的 2D 矢量的方向
【发布时间】:2012-01-02 10:10:24
【问题描述】:

我有一个游戏手柄摇杆的输入,它是一个向量。该向量的值范围定义了一个矩形内的一个圆,该矩形的范围为 -1、-1 到 +1、+1。

我想知道向量接近 8 个可能方向中的哪一个。向量为(0, 0)的情况不用担心,我会单独处理。 我该怎么做?

注意:这是一个游戏,所以这个功能会很频繁地运行。任何加速函数的方法都会有所帮助,例如我知道我可以使用点积和触发来计算我的向量和每个方向向量之间的角度,但是我想知道是否可以做一些更好的事情,因为我不需要准确的角度。

【问题讨论】:

    标签: c# xna trigonometry 2d-vector


    【解决方案1】:

    想象在 -1..1 方格内有一个方格,其中摇杆位置 (X) 位于其中一侧:

    +-----------------+  +-----------------+
    |                 |  |                 |
    |                 |  |                 |
    |          X      |  |    +-----X-+    |
    |                 |  |    |       |    |
    |        O        |  |    |   O   |    |
    |                 |  |    |       |    |
    |                 |  |    +-------+    |
    |                 |  |                 |
    |                 |  |                 |
    +-----------------+  +-----------------+
    

    您只需要找出坐标在哪一边,并检查它是否更靠近边的中心或角落。如果内方格太小,可以考虑把棍子居中。

    类似:

    Public enum Direction {
      None,
      LeftUp, Up, RightUp, Right, RightDown, Down, LeftDown, Left
    }
    
    public Direction GetDirection(double x, double y) {
      double absX = Math.Abs(x);
      double absY = Math.Abs(y);
      if (absX < 0.1 && absY < 0.1) {
        // close to center
        return Direction.None;
      }
      if (absX > absY) {
        // vertical side
        double half = absX * 0.4142;
        if (x > 0) {
          // left side
          if (y > half) return Direction.LeftDown;
          if (y < -half) return Diretion.LeftUp;
          return Direction.Left;
        } else {
          // right side
          if (y > half) return Direction.RightDown;
          if (y < -half) return Direction.RightUp;
          return Direction.Right;
        }
      } else {
        // horisontal side
        double half = absY * 0.4142;
        if (y > 0) {
          // bottom
          if (x > half) return Direction.RightDown;
          if (x < -half) return Direction.LeftDown;
          return Direction.Down;
        } else {
          // top
          if (x > half) return Direction.RightUp;
          if (x < -half) return Direction.LeftUp;
          return Direction.Up;
        }
      }
    }
    

    没有三角函数,只是简单的比较,所以应该很快。 :)

    (虽然我用三角法计算了点0.4142,也就是tan(22.5),或者角度为45/2边的位置。)

    【讨论】:

    • 解决问题的好方法。谢谢!
    【解决方案2】:

    sin a / cos a = tan a,

    你有

    Y = 罪一个

    X = cos a

    所以,对 Y/X 应用反切函数,你就会得到角度。

    编辑:在一个完整的圆中,有两个角具有相同的正切值(aa + pi)。使用 X 和 Y 的符号来确定哪一个是有效的。

    【讨论】:

    • 我认为他知道三角,但担心内置函数会太慢。
    • @driis:没错,我只会在需要时进行优化。但是我认为鉴于我的要求没有得到向量之间的确切角度(它只确定哪个是最小的),我认为其他方法可能是可用的。
    • @GeorgeDuckett 然后为 X/Y 定义“限制”。 X/Y 向右移动。 tan(PI/8) 向右和向上..
    • 当然,如果控制器给你一个归一化的 (X^2 + Y^2) = 1 输入,你可以将 X 与极限角的 cos 进行比较并保存除法。
    • 这不是我原始帖子的想法,但如果您只需要知道向量也更接近哪个方向,它会很快。无论如何,看起来我没有预先计算方向的 tan,而是限制值(vg,预先计算 tan 22,5 和 tan 67,5,如果 X/Y 介于这些值之间,那么-如果它是第一象限-,更近的方向是 45 度)
    【解决方案3】:

    您可以使用预先构建的 tan^-1 近似表。根据输入向量的大小计算角度应该非常快,并且您可能不需要表格中的非常大的分辨率(实际上,如果您只需要 8 个离散方向,表格中的 8 个条目就足够了)。

    【讨论】:

    • 如果您有时间详细说明,我将不胜感激,因为我以前没有处理过查找表。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多