旋转缓和算法在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;
}

我开始怀疑是不是我的类型或类型转换出现了问题。如果有人有任何想法,我们将非常感谢您的意见。

旋转缓和算法在XNA中不起作用

这是用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);
    }
}