Problèmes de détection de collision 2D basés sur des tuiles

8

J'essaie de suivre ce tutoriel http://www.tonypa.pri.ee/tbw/tut05.html pour implémenter des collisions en temps réel dans un monde basé sur les tuiles.

Je trouve les coordonnées centrales de mes entités grâce à ces propriétés:

public float CenterX
{
    get { return X + Width / 2f; }
    set { X = value - Width / 2f; }
}
public float CenterY
{
    get { return Y + Height / 2f; }
    set { Y = value - Height / 2f; }
}

Ensuite, dans ma méthode de mise à jour, dans la classe de joueur, qui est appelée chaque image, j'ai ce code:

public override void Update()
{
    base.Update();

    int downY = (int)Math.Floor((CenterY + Height / 2f - 1) / 16f);
    int upY = (int)Math.Floor((CenterY - Height / 2f) / 16f);
    int leftX =     (int)Math.Floor((CenterX + Speed * NextX - Width / 2f) / 16f);
    int rightX = (int)Math.Floor((CenterX + Speed * NextX + Width / 2f - 1) / 16f);

    bool upleft = Game.CurrentMap[leftX, upY] != 1;
    bool downleft = Game.CurrentMap[leftX, downY] != 1;
    bool upright = Game.CurrentMap[rightX, upY] != 1;
    bool downright = Game.CurrentMap[rightX, downY] != 1;

    if(NextX == 1)
    {
        if (upright && downright)
           CenterX += Speed;
        else
           CenterX = (Game.GetCellX(CenterX) + 1)*16 - Width / 2f;
    }
 }

downY, upY, leftX et rightX devraient respectivement trouver la position Y la plus basse, la position Y la plus élevée, la position X la plus à gauche et la position X la plus à droite. J'ajoute + Speed ​​* NextX car dans le tutoriel la fonction getMyCorners est appelée avec ces paramètres:

getMyCorners (ob.x+ob.speed*dirx, ob.y, ob);

Les méthodes GetCellX et GetCellY:

public int GetCellX(float mX)
{
    return (int)Math.Floor(mX / SGame.Camera.TileSize); 
}
public int GetCellY(float mY)
{
    return (int)Math.Floor(mY / SGame.Camera.TileSize); 
}

Le problème est que le joueur "scintille" en frappant un mur, et la détection des coins ne fonctionne même pas correctement car elle peut chevaucher des murs qui ne touchent qu'un des coins. Je ne comprends pas ce qui ne va pas. Dans le didacticiel, les champs ob.x et ob.y doivent être les mêmes que mes propriétés CenterX et CenterY, et ob.width et ob.height doivent être identiques à Width / 2f et Height / 2f. Mais cela ne fonctionne toujours pas.

Merci de votre aide.

Vee
la source
Testez-vous la collision une fois que le joueur est à cet endroit et repoussez-la s'il entre en collision ou testez-vous si le prochain coup est une collision?
kyndigs
Je recommanderais d'ajouter une vérification de la touche dans cette fonction de mise à jour qui interrompra le processus en cours lorsque vous appuyez sur la touche. Appuyez ensuite sur la touche lorsque le joueur "scintille" et parcourez le débogueur. (faites attention à ce qui arrive aux chiffres) Essayez de savoir ce qui arrive aux chiffres quand il scintille.
Michael Coleman, le

Réponses:

1

Quelques suggestions, bien que je ne sois pas sûr qu'elles résoudront le problème car je n'ai pas le code complet à exécuter et à déboguer.

Dans ce code:

if(NextX == 1)
{
    if (upright && downright)
       CenterX += Speed;
    else
       CenterX = (Game.GetCellX(CenterX) + 1)*16 - Width / 2f;
}

l'instruction else déplace l'objet même s'il ne doit pas se déplacer.
Je suppose que vous essayez de faire affleurer l'objet contre le mur mais peut-être que le calcul est incorrect.
Si vous commentez l'instruction else, l'objet scintille-t-il toujours?

Le calcul semble un peu suspect car il soustrait (Largeur / 2f), puis l'opérateur de définition CenterX effectue à nouveau la même soustraction.

Une autre chose que je voudrais souligner, juste pour aider à la clarté du code, est que vous avez fait les propriétés pour CenterX calculer la valeur d'avant en arrière, mais le code est toujours jonché du même calcul encore et encore.
Cela pourrait bien faire partie du problème. Quoi qu'il en soit, je suggère de créer quelques propriétés supplémentaires et de définir une norme pour chacune d'entre elles. Par exemple, faites du Centre la propriété stockée et calculez-en les autres:

public float CenterX
{
    get { return X; }
    set { X; }
}

public float LeftX
{
    get { return CenterX - Width / 2f; }
    set { CenterX = value + Width / 2f; }
}

public float RightX
{
    get { return CenterX + Width / 2f; }
    set { CenterX = value - Width / 2f; }
}
Paulo Pinto
la source