我正在为 Windows窗体搜索每像素碰撞检测算法/方法。
我搜索过它,但我只找到一个用于XNA(如下所示)。 这种算法难道不符合Windows Forms的概念吗?!
/// <summary>
/// Determines if there is overlap of the non-transparent pixels
/// between two sprites.
/// </summary>
/// <param name="rectangleA">Bounding rectangle of the first sprite</param>
/// <param name="dataA">Pixel data of the first sprite</param>
/// <param name="rectangleB">Bouding rectangle of the second sprite</param>
/// <param name="dataB">Pixel data of the second sprite</param>
/// <returns>True if non-transparent pixels overlap; false otherwise</returns>
static bool IntersectPixels(Rectangle rectangleA, Color[] dataA,
Rectangle rectangleB, 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;
}
}
}
问题在于,我不知道如何初始化Color []数组。
答案 0 :(得分:2)
以下是适用于常规Winforms GDI+ Bitmaps & Lockbits
的修改:
static bool IntersectPixels(Rectangle rectangleA, Bitmap bmpA,
Rectangle rectangleB, Bitmap bmpB)
{
bool collision = false;
Size s1 = bmpA.Size;
Size s2 = bmpB.Size;
PixelFormat fmt1 = bmpA.PixelFormat;
PixelFormat fmt2 = bmpB.PixelFormat;
Rectangle rect = new Rectangle(0, 0, s1.Width, s1.Height);
Rectangle rectB = new Rectangle(0, 0, s2.Width, s2.Height);
BitmapData bmp1Data = bmpA.LockBits(rect, ImageLockMode.ReadOnly, fmt1);
BitmapData bmp2Data = bmpB.LockBits(rectB, ImageLockMode.ReadOnly, fmt2);
int size1 = bmp1Data.Stride * bmp1Data.Height;
int size2 = bmp2Data.Stride * bmp2Data.Height;
byte[] data1 = new byte[size1];
byte[] data2 = new byte[size2];
System.Runtime.InteropServices.Marshal.Copy(bmp1Data.Scan0, data1, 0, size1);
System.Runtime.InteropServices.Marshal.Copy(bmp2Data.Scan0, data2, 0, size2);
// 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++)
{
// Color data are BGRA!
// Get the alpha (+3!) value of both pixels at this point
byte colorA = data1[(x - rectangleA.Left) +
(y - rectangleA.Top) * rectangleA.Width + 3];
byte colorB = data2[(x - rectangleB.Left) +
(y - rectangleB.Top) * rectangleB.Width + 3];
// If both pixels are not completely transparent,
if (colorA != 0 && colorB != 0)
{
// then an intersection has been found
{ collision = true; goto done; }
}
}
}
done:
bmpA.UnlockBits(bmp1Data);
bmpB.UnlockBits(bmp2Data);
return collision;
}
为了检查与完全不透明矩形的碰撞,可以大大简化代码。您只传递该对象的边界(RectangleB
):
static bool IntersectPixels(Rectangle rectangleA, Bitmap bmpA, Rectangle rectangleB)
{
bool collision = false;
Size s1 = bmpA.Size;
Rectangle rect = new Rectangle(0, 0, s1.Width, s1.Height);
rectangleB.Intersect(rectangleA);
BitmapData bmp1Data = bmpA.LockBits(rect, ImageLockMode.ReadOnly, bmpA.PixelFormat);
int size1 = bmp1Data.Stride * bmp1Data.Height;
byte[] data1 = new byte[size1];
System.Runtime.InteropServices.Marshal.Copy(bmp1Data.Scan0, data1, 0, size1);
// Check every point within the intersection bounds
for (int y = rectangleB.Top; y < rectangleB.Bottom; y++)
{
for (int x = rectangleB.Left; x < rectangleB.Right; x++)
{
// Get the alpha value of both pixels at this point
byte colorA = data1[(x - rectangleA.Left) +
(y - rectangleA.Top) * rectangleA.Width + 3];
// If a non-tranparent pixel
if (colorA != 0 ) { collision = true; goto done; }
}
}
done:
bmpA.UnlockBits(bmp1Data);
return collision;
}
我做了一些测试,但我不确定我是否遗漏了一些东西..如果您发现任何错误,请回来!