Il vincolo di area fa esplodere la mia simulazione di fisica se un corpo lo colpisce troppo velocemente

StackOverflow https://stackoverflow.com/questions/1610666

Domanda

Ho una simulazione fisica e ti permette di posizionare vincoli di area, in modo che i corpi all'interno non escano da quell'area. Tuttavia, se un atomo supera una delle "pareti". del vincolo di area fa esplodere la simulazione fisica. Perché fa questo? Metodo di aggiornamento:

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;
    }
}
È stato utile?

Soluzione 3

Non sapresti, dopo circa mezz'ora di hacking insensato, ho pensato semplicemente di non applicare la correzione della posizione. Ciò l'ha risolto come un fascino. Per tutti gli interessati, ecco il codice aggiornato:

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

Altri suggerimenti

Vedo che stai facendo calcoli con un passo temporale costante T. Quando modellizzi le collisioni attraverso su ogni passo dovresti usare un passo temporale pari al tempo minimo prima che uno qualsiasi degli atomi raggiunga un ostacolo.

Rendi variabile la fase temporale e gli atomi non potranno mai "tunnel". ostacoli.

P.S. Ci sono molte ottimizzazioni nel rilevamento delle collisioni, per favore leggi gli articoli di gamedev per informazioni su queste.

P.S. Un bug?

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

La forza viene creata separatamente per la riflessione X e Y. Cosa succede quando l'atomo entra in un angolo? Verrà applicata solo la seconda forza.

P.P.S: usa epsilon

Un'altra nota importante: se usi il virgola mobile, l'errore viene accumulato e dovresti usare eps:

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

dove eps è un numero molto più piccolo delle dimensioni normali nella tua attività, ad es. 0.000001.

Sembra che tu abbia già risolto il problema, ma noto che "forza" sembra essere sbagliato. Allontana l'atomo lontano dal confine, anche se si trova dalla parte sbagliata. Supponiamo che un atomo abbia superato _max.X:

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

Ora " force " sarà nella direzione + x e la distanza dell'atomo dal muro raddoppierà con ogni iterazione. Boom!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top