2012-10-10 40 views
1

幾小時前我問了一個類似的問題,但我認爲在這個問題中有太多的信息,所以我刪除了那一個,並使這一個更相關。減速不按預期工作

我試圖移動一個對象在指定時間內加速度遞減,但在對象到達目的地之前加速度達到0。

我計算加速這樣的:

//Linear acceleration starts at 0 and finishes at 2. 
acceleration = this.elapsed/(this.duration/2.0f); 

加速度爲0和2之間的值取決於有多少時間已過。經過時間接近(總)持續時間時,該值將接近2。

所以計算減速,我會做:

//Linear deceleration starts at 2 and finishes at 0. 
acceleration = 2.0f - this.elapsed/(this.duration/2.0f); 

這似乎工作得很好,但減速的對象永遠不會到達目的地,大約99%的elapsedTime變得比總時長的距離,導致加速度變爲負值。換句話說,它似乎以1%的速度減速過快。

原始加速度完美地工作,線速度也是如此。這只是減速不能正常工作。

我做錯了什麼?

感謝

+1

請說明你表達的數量(加速度,速度,位移,時間?)以及相關變量的單位。正如我現在讀的那樣,你正在設置加速=時間/時間,這是沒有意義的。 –

+0

什麼樣的數據類型已經過了,持續時間是多少?他們也漂浮或是整數? – mclark1129

+0

在我的代碼中,目前持續時間是2000年,這意味着對象需要2秒才能到達目的地。 已用時間表示物體離開初始位置後已移動了多長時間。所以當它移動1秒時,加速度將會是1.0f。當它移動0.5f秒時,加速度將是0.5等。然後,我將其反轉爲減速,所以在0.5秒之後,如果物體正在減速,則加速度爲1.5f。這使我的平均加速度爲1.0,因此它在到達目的地的同時沒有加速的物體。 – Orujimaru

回答

1

沒有看到您的完整代碼,我認爲這個問題可能是由於在某處for循環中使用float作爲迭代變量。

以下面的程序爲例,我能夠複製,當我試圖直接使用float作爲我的迭代變量時,浮點精度會在循環中某處出現某種程度的錯誤。

float duration = 10f; 

for(float elapsed = 0.0f; elapsed <= duration; elapsed = elapsed + 0.1f) { 
    Console.WriteLine(2.0f - elapsed/(duration/2.0f)); 
} 

Console.ReadLine(); 

這個程序的輸出是:

2 
1.98 
1.96 
1.94 
1.92 
1.9 
1.88 
1.86 
1.84 
1.82 
1.8 
1.78 
1.76 
1.74 
1.72 
1.7 
1.68 
1.66 
1.64 
1.62 
1.6 
1.58 
1.56 
1.54 
1.52 
1.5 
1.48 
1.46 
1.44 
1.42 
1.4 
1.38 
1.36 
1.34 
1.32 
1.3 
1.28 
1.26 
1.24 
1.22 
1.2 
1.18 
1.16 
1.14 
1.12 
1.1 
1.08 
1.06 
1.04 
1.02 
1 
0.9800005 
0.9600005 
0.9400005 
0.9200006 
0.9000006 
0.8800006 
0.8600006 
0.8400006 
0.8200006 
0.8000007 
0.7800007 
0.7600007 
0.7400007 
0.7200007 
0.7000008 
0.6800008 
0.6600008 
0.6400008 
0.6200008 
0.6000009 
0.5800009 
0.5600009 
0.5400009 
0.5200009 
0.500001 
0.480001 
0.460001 
0.440001 
0.420001 
0.400001 
0.3800011 
0.360001 
0.3400009 
0.3200008 
0.3000008 
0.2800007 
0.2600006 
0.2400005 
0.2200005 
0.2000004 
0.1800003 
0.1600002 
0.1400001 
0.1200001 
0.1 
0.07999992 
0.05999985 
0.03999977 
0.01999969 

你可以看到,大約一半通過精度射擊的出路,這是因爲迭代變量本身的精度被搞砸了。

在第二個示例中,我使用integer作爲迭代變量,而我只是將integer縮放到每個迭代中的我的計算中。這可以防止迭代變量從去所有扭曲:

float duration = 10f; 
float offset_scale = 10.0f; 

for (int elapsed = 0; elapsed <= (duration * offset_scale); elapsed++) { 
    Console.WriteLine(2.0f - (elapsed/offset_scale)/(duration/2.0f)); 
} 

Console.ReadLine(); 

這個程序的輸出是:

2 
1.98 
1.96 
1.94 
1.92 
1.9 
1.88 
1.86 
1.84 
1.82 
1.8 
1.78 
1.76 
1.74 
1.72 
1.7 
1.68 
1.66 
1.64 
1.62 
1.6 
1.58 
1.56 
1.54 
1.52 
1.5 
1.48 
1.46 
1.44 
1.42 
1.4 
1.38 
1.36 
1.34 
1.32 
1.3 
1.28 
1.26 
1.24 
1.22 
1.2 
1.18 
1.16 
1.14 
1.12 
1.1 
1.08 
1.06 
1.04 
1.02 
1 
0.98 
0.96 
0.94 
0.92 
0.9 
0.88 
0.86 
0.84 
0.82 
0.8 
0.78 
0.76 
0.74 
0.72 
0.7 
0.68 
0.66 
0.64 
0.62 
0.6 
0.58 
0.56 
0.54 
0.52 
0.5 
0.48 
0.46 
0.44 
0.42 
0.4 
0.38 
0.36 
0.34 
0.32 
0.3 
0.28 
0.26 
0.24 
0.22 
0.2 
0.18 
0.16 
0.14 
0.12 
0.1 
0.08 
0.06 
0.04 
0.02 
0 

你可以看到,精度從不瘋狂了,結果在0結束的權利。

+0

這真是一個非常好的電話,我認爲這可能是我的問題。但我不知道如何解決它,因爲我使用XNA的遊戲循環。我試着將浮點數轉換爲整數/雙精度/小數而沒有成功。無論使用什麼樣的價值,加速度/常數都能正常工作,但減速從不起作用。然而,我想出了一個解決方法,當經過時間達到了我強制該值達到最大值的時間(現在對象不會失去同步,並且根本看不到跳轉,因爲它只有> 1 %)。無論如何,我會選擇你的答案,我認爲它可以幫助其他人。 – Orujimaru

+0

我想補充一點,加速時可能會發生同樣的情況:加速度可能會超過2.0,減速度與2.0相同。但是,無論如何,自從它達到目標以來,我都不會注意到加速超過2.0。這可能與XNA的GameTime有關嗎? – Orujimaru

1

你可以嘗試使用C#鉗位功能的花車:http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.mathhelper.clamp.aspx

acceleration = MathHelper.Clamp(2.0f - this.elapsed/(this.duration/2.0f), 0.0, 2.0); 

它只是設置的第一個參數一個最小和最大的價值。

+0

感謝您的建議,我不知道MathHelper。這使我的代碼的其他部分更加清潔。但是恐怕它沒有解決我的問題。該對象仍然沒有到達目的地。 – Orujimaru