2012-02-09 53 views
0

我試圖緩和(逐漸移動)對象到任意位置的旋轉。旋轉角度由虛擬拇指類決定,該類返回-1和1之間的X/Y座標。如果拇指沒有移動,則旋轉回到0,除非我正在補償角度精靈的形象。旋轉緩動算法在XNA中不起作用

我遇到的問題是,此代碼將只允許大約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; 
} 

我開始懷疑是否有與我的類型或強制轉換是導致該問題的問題。如果任何人有任何想法,您的意見非常感謝。

+0

什麼不在這裏工作了? – Tigran 2012-02-09 18:52:12

+0

@Tigran - 旋轉不連續。在任一方向旋轉1.5次後,它會撞擊牆壁,然後折回。另外,當放開拇指按鈕時,它會從它的方向回到0(在這種情況下爲-1.57097)。請重新閱讀該問題以進行澄清。 – ImKevinJones 2012-02-09 19:12:48

回答

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); 

收轉功能如下:

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); 
    } 
} 
0

這是使用XML編寫的C#,所以actionscript並行可能不適用,但我敢打賭,它確實如此。在Flash中,旋轉在每幀結束時進行調整,因爲在存儲123456789度的旋轉變換時沒有什麼好處。所以變換重置爲旋轉的模值。

但是,在計算最短輪轉時,如果您期待某些大數並將其與其他數字進行比較,而不是使用其模數值計算它們的相對位置,則可能會遇到問題。

也許這是問題的根源。它只是一個猜測。

在你不熟悉它的奇怪機會上,模運算符 - 又名百分號 - 「%」將會給你餘下的除法。這對循環的數字很有幫助,如網格對齊和旋轉。

例子:

21 % 5 = 1; 
720 % 360 = 0; 
+0

感謝您的意見,但我不明白如何將該邏輯應用於我的問題。這更多地告訴我,我可以在計算最短旋轉時遇到問題。另外,不太清楚「使用XML編寫C#」的含義。 – ImKevinJones 2012-02-10 04:53:48