这是一个代码,用于旋转船以跟随直线。关节只是线上的Vector2
。左边是0 degrees
。正如你所看到的,当船从0
到360
,或者反之亦然时,它会出现故障。
float LookAt(Vector2 joint)
{
float deltaY = rect.y - joint.Y; // Calculate Delta y
float deltaX = joint.X - rect.x; // Calculate delta x
float angle = (float)(Math.Atan2(deltaY, deltaX) * 180.0 / Math.PI) + 90; // Find angle
float amountToRotate = angle - rotation;
amountToRotate *= 0.05f;
Console.WriteLine($"Rotation: {rotation} Angle: {angle} Amount: {amountToRotate}");
return rotation + amountToRotate;
}
我使用amountToRotate变量,因为我希望旋转稍微平滑一点(在GIF上显示不好(。
https://gyazo.com/cd907763665ac41a2c8f8e5d246ab292
非常感谢您的帮助。
(如果有什么不同的话,我也会在Raylib中这样做(。
因为atan2((返回的值介于-PI和+PI之间或介于-180和+180度之间。因此,如果你的船看起来像170度,而下一个关节是179度,那么你的amountToRotate是+9度,这很好。但是,如果你的船看起来是180度,而你的关节是-180度,你的amountToRotate突然变成-360度(-180-180(,它正对着正x轴。您从amountToRotate中减去5%,并将其添加到当前旋转中(180-360*0.05=162(,这意味着船正在远离节点。
作为一个快速解决方案,您可以将角度转换为360度:
angle = (angle + 360) % 360;
但是,在正x轴的方向上,你仍然会遇到问题。更好的解决方案是计算两个矢量之间的角度并将其反转:
angleTowardsV2FromV1 = -(Math.atan2(v1.y, v1.x) - Math.atan2(v2.y, v2.x))
在你的情况下,这看起来像:
angle = (-(Math.atan2(Math.sin(rotation*Math.PI/180), Math.cos(rotation*Math.PI/180)) - Math.atan2(deltaY, deltaX)))*180/Math.PI
而且,如果你只取角度的5%,旋转就永远不会到达那里。我认为,将角度限制在+-5会更明智。例如:
const clamp = (num, min, max) => Math.min(Math.max(num, min), max);
angle = clamp(angle, -5, +5);
而只是回报:
return rotation + angle;
我希望这能有所帮助。