WindowsForms的每像素碰撞检测算法

我正在为Windows窗体搜索每像素碰撞检测算法/方法。

我搜索过它,但我只找到一个用于XNA(如下所示)。 这种算法难道不符合Windows Forms的概念吗?!

///  /// Determines if there is overlap of the non-transparent pixels /// between two sprites. ///  /// Bounding rectangle of the first sprite /// Pixel data of the first sprite /// Bouding rectangle of the second sprite /// Pixel data of the second sprite /// True if non-transparent pixels overlap; false otherwise 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 []数组。

以下是适用于常规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; } 

我做了一些测试,但我不确定我是否遗漏了一些东西..如果您发现任何错误,请回来!