简体   繁体   中英

Pixel-Perfect Collision With Texture Rotation

I have pixel-perfect collision down, but it only works with the texture rotated at 0 radians. Here is my code for determining the pixel-perfect collision-

public static bool IntersectPixels(Texture2D sprite, Rectangle rectangleA, Color[] dataA, Texture2D sprite2, Rectangle rectangleB, Color[] dataB)
{
    sprite.GetData<Color>(dataA);
    sprite2.GetData<Color>(dataB);

    // Find the bounds of the rectangle intersection
    int top = Math.Max(rectangleA.Top, rectangleB.Top);
    int bottom = Math.Min(rectangleA.Bottom, rectangleB.Bottom);
    int left = Math.Max(rectangleA.Left, rectangleB.Left);
    int right = Math.Min(rectangleA.Right, rectangleB.Right);

    // Check every point within the intersection bounds
    for (int y = top; y < bottom; y++)
    {
        for (int x = left; x < right; x++)
        {
            // Get the color of both pixels at this point
            Color colorA = dataA[(x - rectangleA.Left) + (y - rectangleA.Top) * rectangleA.Width];
            Color colorB = dataB[(x - rectangleB.Left) + (y - rectangleB.Top) * rectangleB.Width];

            // If both pixels are not completely transparent,
            if (colorA.A != 0 && colorB.A != 0)
            {
                // then an intersection has been found
                return true;
            }
        }
    }

    // No intersection found
    return false;
}

I am having trouble with my collision when it is rotated. How would I go about checking pixel collision with a rotated sprite? Thanks, any help is appreciated.

Ideally, you can exress all transformations with a matrix. That shouldn't be a problem with the helper methods. And if you use matrices, you can easily extend the program without having to change the collision code. Up to now, you can represent a translation with the position of the rectangle.

Let's assume object A has the transformation transA and object B has transB . Then you would iterate over all pixels of object A. If the pixel is not transparent, check which pixel of object B is at this very position and check if this pixel is transparent.

The tricky part is determining which pixel of object B is at a given position. This can be achieved with some matrix math.

You know the position in the space of object A. Firstly, we want to transform this local position to a global position on the screen. This is exactly what transA does. After that, we want to transform the global location to a local location in the space of object B. This is the inverse of transB . So, we have to transform the local position in A with the following matrix:

var fromAToB = transA * Matrix.Invert(transB);
//now iterate over each pixel of A
for(int x = 0; x < ...; ++x)
    for(int y = 0; y < ...; ++y)
    {
        //if the pixel is not transparent, then
        //calculate the position in B
        var posInA = new Vector2(x, y);
        var posInB = Vector2.Transform(posInA, fromAToB);
        //round posInB.X and posInB.Y to integer values
        //check if the position is within the range of texture B
        //check if the pixel is transparent
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM