Question

J'ai une simulation physique qui vous permet de définir des contraintes de zone afin que les corps situés à l'intérieur ne quittent pas cette zone. Cependant, si un atome dépasse l'un des "murs", de la contrainte de zone il explose la simulation physique. Pourquoi fait-il cela? Méthode de mise à jour:

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;
    }
}
Était-ce utile?

La solution 3

Ne le sauriez-vous pas, après environ une demi-heure de piratage insensé, j'ai pensé à tout simplement ne pas appliquer la correction de position. Cela l'a réglé comme un charme. Pour ceux qui sont intéressés, voici le code mis à jour:

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

Autres conseils

Je vois que vous effectuez un calcul avec un pas de temps constant T. Lors de la modélisation des collisions bien que à chaque pas , vous devez utiliser un pas de temps égal au temps minimal requis avant qu'un atome n'atteigne un obstacle.

Définissez une variable de pas de temps, et les atomes ne "tunnel" " obstacles.

P.S. Il y a beaucoup d'optimisations dans la détection de collision, veuillez lire les articles de gamedev pour plus d'informations.

P.S. Un bug?

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

La force est créée séparément pour les réflexions X et Y. Que se passe-t-il quand l'atome entre dans un coin? Seule une deuxième force sera appliquée.

P.P.S: utilisez epsilon

Encore une remarque importante: si vous utilisez une virgule flottante, l'erreur est accumulée et vous devez utiliser eps:

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

où eps est un nombre beaucoup plus petit que la taille normale dans votre tâche, par exemple. 0,000001.

Vous semblez déjà avoir résolu le problème, mais je remarque que "force" semble être faux. Il déplace l’atome loin de la frontière, même s’il est du mauvais côté. Supposons qu'un atome ait dépassé _max.X:

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

Maintenant " forcer " sera dans la direction + x, et la distance de l'atome au mur doublera à chaque itération. Boom!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top