1

I asked a similar question a few hours ago, but I think there was too much information in that question so I deleted that one and made this one more relevant.

I'm trying to move an object with a decreasing acceleration in a specified time but the acceleration reaches 0 before the object reaches the destination.

I calculate acceleration like this:

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

Acceleration will be a value between 0 and 2 depending on how much time has elapsed. The value will be closer to 2 when elapsed is closer to (total) duration.

So to calculate a deceleration I would do:

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

This appears to work just fine but the decelerating object never reaches the destination, at around 99% of the distance the elapsedTime becomes greater than total duration, causing the acceleration to become negative. In other words, it appears to have decelerated about 1% too fast.

The original acceleration works perfectly, so does the linear velocity. It's just the deceleration that isn't working properly.

Am I doing something wrong?

Thanks

4

2 回答 2

1

在没有看到完整代码的情况下,我认为问题可能是由于在某处float的循环中使用 a 作为迭代变量。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

您可以看到大约一半的精度射出,这是因为迭代变量本身的精度被搞砸了。

在第二个示例中,我使用 aninteger作为迭代变量,我只是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 回答
1

您可以尝试对浮点数使用 C# Clamp 函数: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 回答