旋转缓和算法在XNA中不起作用
本文关键字:XNA 不起作用 算法 旋转 | 更新日期: 2023-09-27 18:24:01
我正在尝试将对象的旋转轻松(逐渐移动)到任意位置。旋转角度由Virtual Thumbstick类确定,该类返回-1和1之间的X/Y坐标。如果拇指摇杆上没有移动,我将旋转回0,除非我补偿精灵图像的角度。
我遇到的问题是,这个代码只允许大约1.5次旋转(在-3*PI和3*PI之间),而不是连续旋转。将Math.Atan2与拇指操纵杆的X/Y坐标一起使用,返回的角度被限制在-PI和PI之间,但允许连续旋转。此外,如果我向一个方向旋转对象并释放拇指棒,它将从原来的方向旋转回顶部。我希望它在最短的路线上旋转回到顶部。
if (VirtualThumbsticks.LeftThumbstick.Length() > .2f)
{
double rotateTo = Math.Atan2(VirtualThumbsticks.LeftThumbstick.Y, VirtualThumbsticks.LeftThumbstick.X);
if (rotateTo > Rotation + Math.PI) rotateTo -= (Math.PI * 2);
if (rotateTo < Rotation - Math.PI) rotateTo += (Math.PI * 2);
Rotation += (rotateTo - Rotation) * 0.2;
}
else
{
Rotation += (-1.57079 - Rotation) *0.2;
}
如果有任何Flash/ActionScript游戏开发人员知道我在说什么,请加入进来,因为我可以将其应用于C#。
提前谢谢大家!
编辑:
这段代码在AS3:中完美工作
function enterFrameHandler(e:Event):void
{
var curMouseX = Math.round(-(arrow.x - stage.mouseX));//(stage.stageWidth/2)-(stage.mouseX/2);
var curMouseY = Math.round(-(arrow.y - stage.mouseY));//(stage.stageHeight/2)-(stage.mouseY/2);
var angleTo:Number = Math.atan2(curMouseX, -curMouseY) * TO_DEGREES;
if (angleTo > arrow.rotation+180) angleTo -= 360;
if (angleTo < arrow.rotation-180) angleTo += 360;
tf_angle.text = angleTo.toString();
tf_mouseX.text = curMouseX.toString();
tf_mouseY.text = curMouseY.toString();
arrow.rotation += (angleTo - arrow.rotation) * 0.2;
}
我开始怀疑是不是我的类型或类型转换出现了问题。如果有人有任何想法,我们将非常感谢您的意见。
这是用XML在C#中编写的,所以actionscript并行可能不适用,但我敢打赌它适用。在Flash中,旋转是在每帧结束时调整的,因为存储123456789度的旋转变换几乎没有好处。因此变换重置为旋转的模值。
然而,在计算最短旋转时,如果您期望某个大数字,并将其与其他数字进行比较,而不是使用它们的模值计算它们的相对位置,则可能会遇到问题。
也许这就是问题的根源。这只是猜测。
偶尔你不熟悉它,模运算符——也就是百分号——"%"会给你除法的余数。这对循环的数字很有帮助,比如网格对齐和旋转。
示例:
21 % 5 = 1;
720 % 360 = 0;
问题已经解决。问题在于旋转值没有"标准化"。基本上,如果旋转值超过Math.PI*2,则它必须返回0……如果旋转值低于0,则必须返回Math.PI@2。
这个页面上的最后一条评论已经解决了我的问题,现在旋转已经正常化了。
http://forums.create.msdn.com/forums/t/27527.aspx
我得到的代码:
if (VirtualThumbsticks.LeftThumbstick.Length() > .2f)
{
float angleTo = (float)Math.Atan2(VirtualThumbsticks.LeftThumbstick.Y, VirtualThumbsticks.LeftThumbstick.X);
if (angleTo > Rotation + Math.PI) angleTo -= (float)(Math.PI * 2);
if (angleTo < Rotation - Math.PI) angleTo += (float)(Math.PI * 2);
accelerationRotation += (angleTo - Rotation) * (float)0.25;
}
else
{
accelerationRotation += ((float)(Math.PI / 2) - Rotation) * (float)0.2;
}
Rotation = Wrap(accelerationRotation, 0, (float)Math.PI * 2);
Wrap函数如下:
public static float Wrap(float value, float lower, float upper)
{
unchecked
{
if (lower >= upper)
{
throw new ArithmeticException("rotary bounds out of negative or zero size");
}
float distance = upper - lower;
float times = (float)Math.Floor((value - lower) / distance);
return value - (times * distance);
}
}