Ottieni dettagli sulla collisione da Rectangle.Intersects ()


9

Ho un gioco Breakout in cui, ad un certo punto, rilevo la collisione tra la palla e la paletta con qualcosa del genere:

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

Esiste un modo per ottenere le coordinate esatte della collisione, o qualsiasi dettaglio a riguardo, con la corrente XNA API?

Ho pensato di fare alcuni calcoli di base, come confrontare le coordinate esatte di ciascun oggetto nel momento della collisione. Sarebbe simile a questo:

// 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

Ma non sono sicuro che questo sia il modo corretto di farlo.

Ragazzi avete qualche consiglio su forse un motore che dovrei usare per raggiungere questo obiettivo? O anche buone pratiche di codifica usando questo metodo?

Risposte:


8

I rettangoli di XNA sono piuttosto limitati. Il Rectangle.Intersects()metodo restituisce solo un risultato booleano, quindi dovrai fare più test da solo se vuoi dettagli. È possibile, tuttavia, utilizzare il Rectangle.Intersect(Rectangle, Rectangle)metodo per ottenere il rettangolo in cui i due si sovrappongono. Questo ti darà almeno alcune informazioni su profondità e posizione.


Questa get the rectangle where the two overlapfunzionalità è disponibile sul XNA APIo devo scaricare alcune cose extra, come il Platformer Starter Kit?
Daniel Ribeiro,

1
Quale metodo è questo? Non ricordo che XNA 4.0 supporti Rectangle Rectangle.Intersects(...).
ashes999,

Qualcuno mi ha dato il diritto su StackOverflow: msdn.microsoft.com/en-us/library/…
Daniel Ribeiro,

Ok, con il rettangolo restituito, come posso controllare la posizione della paletta che è stata scontrata dalla palla?
Daniel Ribeiro,

Se sai che la paletta e la palla si intersecano, allora usi le informazioni sulla posizione del rettangolo della paletta che hai controllato in primo luogo, cioè rectangle.Xo rectangle.Yo qualunque cosa tu voglia accedere.
sabato

4

Aggiornamento: se stai usando MonoGame, quindi a partire dalla 3.0 beta, Rectangle Rectangle.Intersect(rectangle, rectangle)non esiste. È possibile utilizzare il codice seguente dal kit XNA Platformer.


È possibile scaricare lo Starter Kit XNA Platformer ( portato su Windows 7 ). Viene fornito con un metodo di estensione dell'helper che restituisce un rettangolo che descrive l'intersezione di due rettangoli:

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

Grazie mille per questo link Posso chiederti perché hai bisogno di utilizzare una versione modificata? Quel porto è ufficiale?
Daniel Ribeiro,

@DanielRibeiro Ho controllato la mia storia e apparentemente non l'ho modificata dopo tutto. Il porto non è ufficiale; Semplicemente non sono riuscito a trovare l'originale. Funziona con MonoGame / C #, che era abbastanza buono per me.
ashes999,

Ma c'è una porta originale, giusto? Non dovrebbe essere una funzionalità così semplice? Comunque, non sto usando MonoGame, solo XNA. Mi consiglieresti ancora di usare questa porta?
Daniel Ribeiro,

Ho dovuto impostare la risposta corretta a ssb, ma grazie mille per questo. Entrerò sicuramente in questa porta! Grazie molto!
Daniel Ribeiro,

1
@DanielRibeiro ah, capisco. Penso che questo metodo non esista in MonoGame, motivo per cui ho finito con questo approccio. Saluti però.
ashes999,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.