Static Method for Per-Pixel Collision Detection
Bounding boxes for 2D collisions are nice, but they aren't going to give you the most realistic collisions when your object isn't shaped like a box. Below is a static method that takes in the textures and positions of two sprites and will let you know if they collide or not.
"Look ma, no rectangles!"
The code itself is based off an example from ZiggyWare (though easier to implement), but since that website doesn't exist anymore, I figure I'd share my take on the code.
public static bool CheckPerPixel(Texture2D texture1, Texture2D texture2, Vector2 position1, Vector2 position2)
{
bool perPixelCollission = false;
uint[] bitsA = new uint[texture1.Width * texture1.Height];
uint[] bitsB = new uint[texture2.Width * texture2.Height];
Rectangle texture1Rectangle = new Rectangle(Convert.ToInt32(position1.X), Convert.ToInt32(position1.Y), texture1.Width, texture1.Height);
Rectangle texture2Rectangle = new Rectangle(Convert.ToInt32(position2.X), Convert.ToInt32(position2.Y), texture2.Width, texture2.Height);
texture1.GetData<uint>(bitsA);
texture2.GetData<uint>(bitsB);
int x1 = Math.Max(texture1Rectangle.X, texture2Rectangle.X);
int x2 = Math.Min(texture1Rectangle.X + texture1Rectangle.Width, texture2Rectangle.X + texture2Rectangle.Width);
int y1 = Math.Max(texture1Rectangle.Y, texture2Rectangle.Y);
int y2 = Math.Min(texture1Rectangle.Y + texture1Rectangle.Height, texture2Rectangle.Y + texture2Rectangle.Height);
for (int y = y1; y < y2; ++y)
{
for (int x = x1; x < x2; ++x)
{
if (((bitsA[(x - texture1Rectangle.X) + (y - texture1Rectangle.Y) * texture1Rectangle.Width] & 0xFF000000) >> 24) > 20 &&
((bitsB[(x - texture2Rectangle.X) + (y - texture2Rectangle.Y) * texture2Rectangle.Width] & 0xFF000000) >> 24) > 20)
{
perPixelCollission = true;
break;
}
}
// Reduce amount of looping by breaking out of this.
if (perPixelCollission)
{
break;
}
}
return perPixelCollission;
}
One word of warning, per-pixel collision detections can be slow. I never run this code by itself for my collision detections. Instead I check first for a rectangular collision and only if that occurs do I perform the per-pixel check.
This article has been view 3599 times.
|