2012-10-10 31 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