如果您用“BAMS”(二进制角度测量系统)来表示角度,则可以完全避免除法(和模)。这个想法是,如果将角度存储在 N 位整数中,则可以使用该整数的整个范围来表示角度。这样,就无需担心超过 360 度的溢出,因为表示的自然 modulo-2^N 属性会为您处理它。
例如,假设您使用 8 位。这会将您的圆切割成 256 个可能的方向。 (您可以选择更多位,但就示例而言,8 位比较方便)。 0x00代表0度,0x40代表90度,0x80代表180度,0xC0代表270度。不用担心“符号”位,BAMS 是角度的天然选择。如果您将 0xC0 解释为“无符号”并缩放为每次计数 360/256 度,则您的角度为 (+192)(360/256) = +270;但如果你将 0xC0 解释为“有符号”,那么你的角度是(-64)(360/256)=-90。请注意,-90 和 +270 在角度方面含义相同。
如果您想将三角函数应用于 BAMS 角度,您可以预先计算表格。有一些技巧可以缩小表格,但您可以看到表格并没有那么大。为 8 位 BAMS 存储双精度值的整个正弦和余弦表不需要超过 4K 的内存,这在当今的环境中是鸡饲料。
既然您提到在游戏中使用它,您可能可以使用 8 位或 10 位表示。任何时候添加或减去角度,都可以使用逻辑 AND 运算将结果强制转换为 N 位,例如,angle &= 0x00FF 表示 8 位。
忘记了最好的部分 (edit)
右转与左转问题可以在 BAMS 系统中轻松解决。只需取差值,并确保只保留 N 个有意义的位。将 MSB 解释为符号位指示您应该转向的方向。如果差值为负,则通过差值的abs()向相反方向转。
这个丑陋的小 C 程序演示了。首先尝试输入 20 10 和 20 30 等。然后尝试通过绕零点来欺骗它。给它 20 -10,它就会向左转。给它 20 350,它仍然左转。请注意,由于它是用 8 位完成的,因此 181 与 180 无法区分,因此如果您输入 20 201 并且它向右转而不是向左转,请不要感到惊讶 - 在 8 位提供的分辨率中,左转和右转这个情况是一样的。输入 20 205,它会走得更短。
#include <stdio.h>
#include <math.h>
#define TOBAMS(x) (((x)/360.0) * 256)
#define TODEGS(b) (((b)/256.0) * 360)
int main(void)
{
double a1, a2; // "real" angles
int b1, b2, b3; // BAMS angles
// get some input
printf("Start Angle ? ");
scanf("%lf", &a1);
printf("Goal Angle ? ");
scanf("%lf", &a2);
b1 = TOBAMS(a1);
b2 = TOBAMS(a2);
// difference increases with increasing goal angle
// difference decreases with increasing start angle
b3 = b2 - b1;
b3 &= 0xff;
printf("Start at %7.2lf deg and go to %7.2lf deg\n", a1, a2);
printf("BAMS are 0x%02X and 0x%02X\n", b1, b2);
printf("BAMS diff is 0x%02X\n", b3);
// check what would be the 'sign bit' of the difference
// negative (msb set) means turn one way, positive the other
if( b3 & 0x80 )
{
// difference is negative; negate to recover the
// DISTANCE to move, since the negative-ness just
// indicates direction.
// cheap 2's complement on an N-bit value:
// invert, increment, trim
b3 ^= -1; // XOR -1 inverts all the bits
b3 += 1; // "add 1 to x" :P
b3 &= 0xFF; // retain only N bits
// difference is already positive, can just use it
printf("Turn left %lf degrees\n", TODEGS(b3));
printf("Turn left %d counts\n", b3);
}
else
{
printf("Turn right %lf degrees\n", TODEGS(b3));
printf("Turn right %d counts\n", b3);
}
return 0;
}