Per Pixel Sprite Sheet Collision Detection

 I’ve seen this question asked a few times but no public answers. How do you detect if two sprites in a sprite sheet collide using per pixel collision detection? The answer for entire sprites is available easily. I made two static methods that can be added to a project to check if two parts of a sprite sheet collide. Soon I will be posting code that handles rotated and scaled sprites as well.


public static bool SpriteSheetCollision(
Rectangle destinationA,
Rectangle? sourceA,
Texture2D textureA,
Rectangle destinationB,
Rectangle? sourceB,
Texture2D textureB)
{
// If the sourceA is null use entire texture
if (sourceA == null)
{
sourceA = new Rectangle(0, 0, textureA.Width, textureA.Height);
}

// Grab the texture data for checking if the pixels collide in the source rectangle
Color[] textureDataA = new Color[sourceA.Value.Width * sourceA.Value.Height];
textureA.GetData(0, sourceA, textureDataA, 0, textureDataA.Length);

// If the sourceB is null use the entire texture as the source rectangle
if (sourceB == null)
{
sourceB = new Rectangle(0, 0, textureB.Width, textureB.Height);
}

// Grab the texture data for checking if the pixels collide in the source rectangle
Color[] textureDataB = new Color[sourceB.Value.Width * sourceB.Value.Height];
textureB.GetData(0, sourceB, textureDataB, 0, textureDataB.Length);

// Call the per pixel collision detection code
return ColorDataCollides(destinationA, textureDataA, destinationB, textureDataB);
}

public static bool ColorDataCollides(Rectangle a, Color[] textureDataA, Rectangle b, Color[] textureDataB)
{
// Find the bounds of the rectangle intersection
int top = Math.Max(a.Top, b.Top);
int bottom = Math.Min(a.Bottom, b.Bottom);
int left = Math.Max(a.Left, b.Left);
int right = Math.Min(a.Right, b.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 = textureDataA[(x - a.Left) +
(y - a.Top) * a.Width];
Color colorB = textureDataB[(x - b.Left) +
(y - b.Top) * b.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;
}