Obtenez les détails de collision de Rectangle.Intersects ()

9

J'ai un jeu Breakout dans lequel, à un moment donné, je détecte la collision entre la balle et la raquette avec quelque chose comme ceci:

// Ball class
rectangle.Intersects(paddle.Rectangle);

Existe-t-il un moyen d'obtenir les coordonnées exactes de la collision ou des détails à ce sujet avec le courant XNA API?

J'ai pensé faire quelques calculs de base, comme comparer les coordonnées exactes de chaque objet au moment de la collision. Cela ressemblerait à quelque chose comme ceci:

// Ball class
if((rectangle.X - paddle.Rectangle.X) < (paddle.Rectangle.Width / 2))
    // Collision happened on the left side
else
    // Collision happened on the right side

Mais je ne suis pas sûr que ce soit la bonne façon de procéder.

Avez-vous des conseils sur peut-être un moteur que je devrais utiliser pour y parvenir? Ou même de bonnes pratiques de codage utilisant cette méthode?

Daniel Ribeiro
la source

Réponses:

8

Les rectangles de XNA sont assez limités. La Rectangle.Intersects()méthode ne renvoie qu'un résultat booléen, vous devrez donc effectuer plus de tests vous-même si vous voulez des détails. Vous pouvez cependant utiliser la Rectangle.Intersect(Rectangle, Rectangle)méthode pour obtenir le rectangle où les deux se chevauchent. Cela vous donnera au moins quelques informations sur la profondeur et l'emplacement.

ssb
la source
Cette get the rectangle where the two overlapfonctionnalité est-elle disponible sur le XNA APIou je dois télécharger des trucs supplémentaires, comme le Platformer Starter Kit?
Daniel Ribeiro
1
De quelle méthode s'agit-il? Je ne me souviens pas que XNA 4.0 prend en charge Rectangle Rectangle.Intersects(...).
ashes999
Quelqu'un m'a donné le droit à stackoverflow: msdn.microsoft.com/en-us/library/…
Daniel Ribeiro
Ok, avec le rectangle retourné, comment puis-je vérifier la position de la palette qui est entrée en collision avec la balle?
Daniel Ribeiro
Si vous savez que la palette et la balle se croisent alors vous utilisez les informations d'emplacement du rectangle de palette que vous avez coché en premier lieu, à savoir rectangle.Xou rectangle.You tout ce que vous voulez accéder.
ssb
4

Mise à jour: si vous utilisez MonoGame, la version bêta 3.0 Rectangle Rectangle.Intersect(rectangle, rectangle)n'existe pas. Vous pouvez utiliser le code ci-dessous à partir du kit XNA Platformer à la place.


Vous pouvez télécharger le kit de démarrage XNA Platformer ( porté sur Windows 7 ). Il est livré avec une méthode d'extension d'assistance qui renvoie un rectangle décrivant l'intersection de deux rectangles:

static class RectangleExtensions
    {
        /// <summary>
        /// Calculates the signed depth of intersection between two rectangles.
        /// </summary>
        /// <returns>
        /// The amount of overlap between two intersecting rectangles. These
        /// depth values can be negative depending on which wides the rectangles
        /// intersect. This allows callers to determine the correct direction
        /// to push objects in order to resolve collisions.
        /// If the rectangles are not intersecting, Vector2.Zero is returned.
        /// </returns>
        public static Vector2 GetIntersectionDepth(this Rectangle rectA, Rectangle rectB)
        {
            // Calculate half sizes.
            float halfWidthA = rectA.Width / 2.0f;
            float halfHeightA = rectA.Height / 2.0f;
            float halfWidthB = rectB.Width / 2.0f;
            float halfHeightB = rectB.Height / 2.0f;

            // Calculate centers.
            Vector2 centerA = new Vector2(rectA.Left + halfWidthA, rectA.Top + halfHeightA);
            Vector2 centerB = new Vector2(rectB.Left + halfWidthB, rectB.Top + halfHeightB);

            // Calculate current and minimum-non-intersecting distances between centers.
            float distanceX = centerA.X - centerB.X;
            float distanceY = centerA.Y - centerB.Y;
            float minDistanceX = halfWidthA + halfWidthB;
            float minDistanceY = halfHeightA + halfHeightB;

            // If we are not intersecting at all, return (0, 0).
            if (Math.Abs(distanceX) >= minDistanceX || Math.Abs(distanceY) >= minDistanceY)
                return Vector2.Zero;

            // Calculate and return intersection depths.
            float depthX = distanceX > 0 ? minDistanceX - distanceX : -minDistanceX - distanceX;
            float depthY = distanceY > 0 ? minDistanceY - distanceY : -minDistanceY - distanceY;
            return new Vector2(depthX, depthY);
        }

        /// <summary>
        /// Gets the position of the center of the bottom edge of the rectangle.
        /// </summary>
        public static Vector2 GetBottomCenter(this Rectangle rect)
        {
            return new Vector2(rect.X + rect.Width / 2.0f, rect.Bottom);
        }
}
cendres999
la source
Merci beaucoup pour ce lien. Puis-je vous demander pourquoi avez-vous eu besoin d'utiliser une version modifiée? Ce port est-il officiel?
Daniel Ribeiro
@DanielRibeiro J'ai vérifié mon historique et apparemment je ne l'ai pas modifié après tout. Le port n'est pas officiel; Je n'ai tout simplement pas pu trouver l'original. Cela fonctionne avec MonoGame / C #, ce qui était assez bon pour moi.
ashes999
Mais il y a un port d'origine, non? N'est-ce pas censé être une fonctionnalité aussi simple? Quoi qu'il en soit, je n'utilise pas MonoGame, juste XNA. Me recommanderiez-vous toujours d'utiliser ce port?
Daniel Ribeiro
J'ai dû définir la bonne réponse ssb, mais merci beaucoup pour cela. Je vais à coup sûr entrer dans ce port! Merci beaucoup!
Daniel Ribeiro
1
@DanielRibeiro ah, je vois. Je pense que cette méthode n'existe pas dans MonoGame, c'est pourquoi j'ai fini par utiliser cette approche. Bravo cependant.
ashes999