Question

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

Was it helpful?

Solution

Without seeing your full code, I think the problem is probably due to using a float as an iteration variable in a for loop somewhere.

Using the following program as an example, I am able to replicate that the floating point precision gets kind of screwed up somewhere in the loop when I try to use the float as my iteration variable directly.

float duration = 10f;

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

Console.ReadLine();

The output of this program is:

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

You can see that about halfway through the precision shoots way out, and that is because the precision for the iteration variable itself gets screwed up.

In the second example, I use an integer as the iteration variable instead and I simply scale the integer to my calculation inside of each iteration. This prevents the iteration variable from going all screwy:

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

The output for this program is:

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

You can see that the precision never goes crazy, and the result ends up right at 0.

OTHER TIPS

You could try to use the C# Clamp function for floats: 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);

It simply sets a min and max value for the first param.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top