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%で、経過時間が合計時間より長くなり、加速度が負になります。つまり、減速が約1%速すぎたようです。

元の加速度は完全に機能し、線速度も完全に機能します。正しく機能していないのは減速だけです。

私は何か間違ったことをしていますか?

ありがとう

4

2 に答える 2

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

最初のパラメータの最小値と最大値を設定するだけです。

于 2012-10-10T16:50:01.717 に答える
1

完全なコードが表示されない場合、問題はおそらくどこかfloatのループで反復変数としてを使用していることが原因だと思います。for

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

精度のシュートの約半分が終了していることがわかります。これは、反復変数自体の精度が台無しになっているためです。

2番目の例では、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になります。

于 2012-10-10T17:20:35.557 に答える