Pergunta

Eu tenho uma simulação de física e permite que você a restrições da área local, para que os corpos dentro não vai sair dessa área. No entanto, se um átomo vai um passado das "paredes" da restrição área ele explode a simulação de física. Por que ele faz isso? método de actualização:

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;
    }
}
Foi útil?

Solução 3

Será que você não sabe, depois de cerca de meia hora de irracional hackers para ele, pensei em simplesmente não aplicar a correção da posição. Que fixa-lo como um encanto. Para qualquer interessado, aqui está o código atualizado:

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

Outras dicas

Eu vejo que você está fazendo o cálculo com um passo constante de tempo T. Ao modelar colisões embora em cada etapa você deve usar etapa tempo igual ao tempo mínimo antes de qualquer um dos átomos de chegar a qualquer obstáculo.

Faça variável passo de tempo, e os átomos jamais "túnel" obstáculos.

P.S. Há uma série de otimizações em detecção de colisão, por favor leia papéis Gamedev para obter informações sobre os.

P.S. Um bug?

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

Força é criado separadamente para X e Y reflexão. O que acontece quando o átomo fica em um canto? Apenas segunda força será aplicada.

P.P.S: Use epsilon

Uma nota mais importante: se você usar ponto flutuante, o erro é acumulado, e você deve usar eps:

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

onde eps é um número muito menor do que os tamanhos normais na sua tarefa, por exemplo, 0,000001.

Você parece ter resolvido o problema já, mas eu aviso que "força" parece estar errado. Ele move o átomo de afastado a partir do limite, mesmo que seja no lado errado. Suponha que um átomo disparou passado _max.X:

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

Agora "força" será no sentido + x, e distância do átomo da parede irá duplicar a cada iteração. Boom!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top