我有一个游戏手柄拇指杆的输入,它是一个向量。向量的值范围定义了一个矩形内的一个圆,该矩形跨越 -1、-1 到 +1、+1。
我想知道向量接近 8 个可能方向中的哪一个。向量为(0, 0)的情况不用担心,我会单独处理。我怎样才能做到这一点?
注意:这是一个游戏,所以这个函数会很频繁地运行。任何加速函数的方法都会有所帮助,例如我知道我可以使用点积和触发来计算我的向量和每个方向向量之间的角度,但是我想知道是否可以做一些更好的事情,因为我不需要准确的角度。
我有一个游戏手柄拇指杆的输入,它是一个向量。向量的值范围定义了一个矩形内的一个圆,该矩形跨越 -1、-1 到 +1、+1。
我想知道向量接近 8 个可能方向中的哪一个。向量为(0, 0)的情况不用担心,我会单独处理。我怎样才能做到这一点?
注意:这是一个游戏,所以这个函数会很频繁地运行。任何加速函数的方法都会有所帮助,例如我知道我可以使用点积和触发来计算我的向量和每个方向向量之间的角度,但是我想知道是否可以做一些更好的事情,因为我不需要准确的角度。
想象一下 -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 的一侧的位置。)
sin a / cos a = tan a,
你有
Y = 罪
X = cos
因此,对 Y/X 应用反向切线函数,您将得到角度。
编辑:在一个完整的圆中,有两个角具有相同的切线值(a
和a
+ pi
)。使用 X 和 Y 的符号来确定哪一个是有效的。
您可以使用 tan^-1 的预先构建的近似表。根据输入向量的大小计算角度应该非常快,并且您可能不需要表格中的非常大的分辨率(实际上,如果您只需要 8 个离散方向,表格中的 8 个条目就足够了)。