Ограничение площади взрывает моё физическое моделирование, если тело врезается в него слишком быстро - PullRequest
1 голос
/ 23 октября 2009

У меня есть физическое моделирование, и оно позволяет вам размещать ограничения области, чтобы тела внутри не выходили из этой области. Однако, если атом проходит мимо одной из «стенок» ограничения области, он взрывает физическое моделирование. Почему он это делает? Метод обновления:

if (!atom.IsStatic)
{
    Vector2 force = Vector2.Zero;
    bool x = false, y = false;
    if (atom.Position.X - atom.Radius < _min.X)
    {
        force = new Vector2(-(_min.X - atom.Position.X), 0);
        if (atom.Velocity.X < 0)
            x = true;
    }
    if (atom.Position.X + atom.Radius > _max.X)
    {
        force = new Vector2(atom.Position.X - _max.X, 0);
        if (atom.Velocity.X > 0)
            x = true;
    }
    if (atom.Position.Y - atom.Radius < _min.Y)
    {
        force = new Vector2(0, -(_min.Y - atom.Position.Y));
        if (atom.Velocity.Y < 0)
            y = true;
    }
    if (atom.Position.Y + atom.Radius > _max.Y)
    {
        force = new Vector2(0, atom.Position.Y - _max.Y);
        if (atom.Velocity.Y > 0)
            y = true;
    }
    atom.ReverseVelocityDirection(x, y);
    if (!atom.IsStatic)
    {
        atom.Position += force;
    }
}

Ответы [ 3 ]

3 голосов
/ 23 октября 2009

Я вижу, что вы делаете вычисления с постоянным шагом по времени T. При моделировании столкновений, хотя на каждом шаге , вы должны использовать шаг по времени, равный минимальному времени, прежде чем любой из атомов достигнет какого-либо препятствия.

Сделайте шаг по времени переменным, и атомы никогда не будут "туннелировать" препятствия.

P.S. Существует множество оптимизаций в обнаружении столкновений, пожалуйста, прочитайте статьи Gamedev для получения информации о них.

P.S. Ошибка?

force = new Vector2(-(_min.X - atom.Position.X), 0);

Сила создается отдельно для X и Y отражения. Что происходит, когда атом попадает в угол? Будет применена только вторая сила.

P.P.S: использовать эпсилон

Еще одно важное замечание: если вы используете с плавающей запятой, ошибка накапливается, и вы должны использовать eps:

abs(atom.Position.Y + atom.Radium - _max.Y) < eps

где eps - это число, намного меньшее, чем обычные размеры в вашей задаче, например 0,000001.

1 голос
/ 29 октября 2009

Вы, кажется, уже решили проблему, но я замечаю, что «сила», кажется, не так. Он отодвигает атом на от границы, даже если он не на той стороне. Предположим, что атом прошел мимо _max.X:

if (atom.Position.X + atom.Radius > _max.X) 
    { 
        force = new Vector2(atom.Position.X - _max.X, 0); 
        ...
    } 

Теперь «сила» будет в направлении + x, и расстояние атома от стены будет удваиваться с каждой итерацией. Boom!

0 голосов
/ 23 октября 2009

Разве вы не знаете, после примерно получаса бездумного хакерства я подумал о том, чтобы просто не применять коррекцию положения. Это исправило это как оберег. Для тех, кто заинтересован, вот обновленный код:

if (!atom.IsStatic)
{
    if (atom.Position.X - atom.Radius < _min.X && atom.Velocity.X < 0)
    {
        atom.ReverseVelocityDirection(true, false);
    }
    if (atom.Position.X + atom.Radius > _max.X && atom.Velocity.X > 0)
    {
        atom.ReverseVelocityDirection(true, false);
    }
    if (atom.Position.Y - atom.Radius < _min.Y && atom.Velocity.Y < 0)
    {
        atom.ReverseVelocityDirection(false, true);
    }
    if (atom.Position.Y + atom.Radius > _max.Y && atom.Velocity.Y > 0)
    {
        atom.ReverseVelocityDirection(false, true);
    }
}
...