3

我有球在四处弹跳,每次它们碰撞时,它们的速度矢量都会因恢复系数而减小。

现在我的球的 CoR 是 .80 。因此,在多次反弹后,我的球“停止”滚动,因为它们的速度变得非常小。

在哪个阶段检查速度值是否足够小以简单地将其称为零是合适的(所以我没有球对它们的微速度做出反应的疯狂抖动)。我之前在一些论坛上读过,人们有时会使用一个 epsilon 常数,一些很小的数字并检查它。

我是否应该定义一个 epsilon 常量并执行以下操作:

if Math.abs(velocity.x) < epsilon then velocity.x = 0

每次我更新球的速度和位置?这是一般的做法吗?将它放在我的 x 和 y 的 Vector 类设置器中是否合理?或者当我计算速度时我应该在我的矢量类之外做它。

另外,如果我使用浮点数作为速度向量,那么合理的 epsilon 值是多少?

4

4 回答 4

1

epsilon 的合理值将取决于系统的约束。如果您以图形方式表示球,那么您的 epsilon 可能对应于每秒 0.1 像素的速度(确保您的停止概念与用户对屏幕对象停止的体验相匹配)。如果您正在进行物理模拟,您需要将其调整到您尝试测量系统的准确度。

至于您检查的频率 - 这也取决于。如果您正在实时模拟某些东西,那么额外的检查可能会很昂贵,并且您需要每 10 次更新或每秒检查一次或其他东西。或者性能可能不是问题,您可以检查每个更新。

于 2008-12-10T00:23:54.397 回答
1

代替 IsStillMoving 函数的 epsilon,也许您可​​以使用 UpdatePosition 函数,根据其速度在逐个对象的基础上进行调度。

我会做这样的事情(在我自己的make-it-as-you-go伪代码中):

void UpdatePosition(Ball b) {

   TimeStamp now = Clock.GetTime();
   float secondsSinceLastUpdate = now.TimeSince(b.LastUpdate).InSeconds;

   Point3D oldPosition = b.Position;
   Point3D newPosition = CalculatePosition(b.Position, b.Velocity, interval);
   b.MoveTo(newPosition);

   float epsilonOfAccuracy = 0.5; // Accurate to one half-pixel
   float pixelDistance = Camera.PixelDistance(oldPosition, newPosition);
   float fps = System.CurrentFramesPerSecond;
   float secondsToMoveOnePixel = (pixelDistance * secondsSinceLastUpdate) / fps;
   float nextUpdateInterval = secondsToMoveOnePixel / epsilonOfAccuracy;

   b.SetNextUpdateAt(now + nextUpdateInterval);
}

快速移动的球会在每一帧上更新。移动较慢的球可能每五或十帧更新一次。已经停止(或几乎停止)的球只会很少更新。

于 2008-12-10T00:43:55.247 回答
0

IMO 你的 epsilon 方法很好。我只是尝试看看游戏中的动画看起来或感觉自然。

于 2008-12-10T00:14:32.593 回答
0

Epsilon 本质上是最小的增量。不幸的是,计算机有不同的“最小”增量,具体取决于浮点表示。我会非常小心(甚至可能比我为安全考虑的计算值更高)玩弄它,特别是如果我希望代码是可移植的。

您可能想要编写一个函数来计算浮点数的最小增量,而不是使用魔法值。

于 2008-12-10T00:49:39.307 回答