Используя значение эпсилона, чтобы определить, не движется ли мяч в игре? - PullRequest
2 голосов
/ 10 декабря 2008

У меня шары подпрыгивают, и каждый раз, когда они сталкиваются, их вектор скорости уменьшается на Коэффициент реституции.

Прямо сейчас CoR моих шаров для моих шаров составляет 0,80. Так что после многих отскоков мои шары «перестали» катиться, потому что их скорость стала смехотворно малой.

На какой стадии уместно проверить, достаточно ли мало значение скорости, чтобы просто назвать его нулем (поэтому у меня нет сумасшедшего дрожания шаров, реагирующих на их микроскорости). Ранее я читал на некоторых форумах, что люди иногда используют константу эпсилона, какое-то небольшое число и проверяют это.

Должен ли я определить константу эпсилона и сделать что-то вроде:

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

Каждый раз, когда я обновляю скорость и положение шаров? Это то, что обычно делается? Было бы разумно поместить это в мои сеттеры классов Vector для x и y? Или я должен делать это вне моего векторного класса, когда я вычисляю скорости.

Кроме того, что было бы разумным значением эпсилона, если бы я использовал числа с плавающей точкой для своего вектора скорости?

Ответы [ 4 ]

1 голос
/ 10 декабря 2008

Разумное значение для epsilon будет зависеть от ограничений вашей системы. Если вы представляете шарик графически, тогда ваш эпсилон может соответствовать скорости, скажем, 0,1 пикселя в секунду (гарантируя, что ваше представление об остановке соответствует восприятию пользователем остановок объектов экрана). Если вы выполняете физическое моделирование, вам нужно настроить его с точностью, с которой вы пытаетесь измерить свою систему.

Что касается того, как часто вы проверяете - это также зависит. Если вы моделируете что-то в реальном времени, дополнительная проверка может быть дорогостоящей, и вам нужно будет проверять каждые 10 обновлений или один раз в секунду или что-то в этом роде. Или производительность не может быть проблемой, и вы можете проверить с каждым обновлением.

1 голос
/ 10 декабря 2008

Вместо эпсилона для функции IsStillMoving, возможно, вы могли бы использовать функцию UpdatePosition, запланированную для каждого объекта в зависимости от его скорости.

Я бы сделал что-то вроде этого (в моем собственном псевдокоде «сделай сам»):

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

Шары, движущиеся очень быстро, будут обновляться на каждом кадре. Шарики, движущиеся медленнее, могут обновляться каждые пять или десять кадров. И шары, которые остановились (или почти остановились), будут обновляться очень и очень редко.

0 голосов
/ 10 декабря 2008

Эпсилон по своей природе - это наименьший возможный прирост. К сожалению, компьютеры имеют свои собственные «минимальные» приращения в зависимости от представления с плавающей запятой. Я был бы очень осторожен (и мог бы даже пойти выше, чем рассчитывал бы просто для безопасности), играя с этим, особенно если я хочу, чтобы код был переносимым.

Возможно, вы захотите написать функцию, которая вычисляет минимальное приращение ваших поплавков, а не использует магическое значение.

0 голосов
/ 10 декабря 2008

ИМО, твой эпсилон-подход хорош. Я бы просто поэкспериментировал, чтобы увидеть, что выглядит или чувствует себя естественно для анимации в игре.

...