WPF判断两个PNG图片是否碰撞

Posted 我丫的是条鱼

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WPF判断两个PNG图片是否碰撞相关的知识,希望对你有一定的参考价值。

这个方法有几个前提

1.两个Image必须在一个Canvas中

2.两个Image的Canvas.Top和Canvas.Left必须赋值

上一篇讲了判断一个PNG图片某个点是否透明 这个基本类似的方法

主题思路

1.利用Rect判断两个Image是否有重合

2.只判断重合部分是否存在碰撞

3.将重合区域分成4块 由外向内判定

下面是代码部分

技术分享
  1   /// <summary>
  2         /// 判断画布上两个Image是否碰撞了
  3         /// </summary>
  4         /// <param name="ig1">Image1</param>
  5         /// <param name="ig2">Image2</param>
  6         /// <returns>是否碰撞</returns>
  7         public static Boolean IsImageInside(System.Windows.Controls.Image ig1, System.Windows.Controls.Image ig2)
  8         {
  9 
 10             if (ig1.Source == null || ig2.Source == null)
 11             {
 12                 return false;
 13             }
 14             Rect containingRect1 = new Rect(Canvas.GetLeft(ig1), Canvas.GetTop(ig1), ig1.ActualWidth, ig1.ActualHeight);
 15             Rect containingRect2 = new Rect(Canvas.GetLeft(ig2), Canvas.GetTop(ig2), ig2.ActualWidth, ig2.ActualHeight);
 16             containingRect1.Intersect(containingRect2);
 17             if (containingRect1.IsEmpty)
 18             {
 19                 return false;
 20             }
 21             System.Windows.Point RectPoint = containingRect1.TopLeft;
 22             BitmapSource m1 = (BitmapSource)ig1.Source;
 23             BitmapSource m2 = (BitmapSource)ig2.Source;
 24             using (System.Drawing.Bitmap bmp1 = new System.Drawing.Bitmap(m1.PixelWidth, m1.PixelHeight, System.Drawing.Imaging.PixelFormat.Format32bppPArgb))
 25             {
 26 
 27                 System.Drawing.Imaging.BitmapData data1 = bmp1.LockBits(
 28                 new System.Drawing.Rectangle(System.Drawing.Point.Empty, bmp1.Size), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
 29                 m1.CopyPixels(Int32Rect.Empty, data1.Scan0, data1.Height * data1.Stride, data1.Stride); bmp1.UnlockBits(data1);
 30 
 31                 double dx1 = 1;
 32                 double dy1 = 1;
 33 
 34                 #region 获取实际图像点
 35 
 36                 #region 获取缩放比例
 37 
 38                 switch (ig1.Stretch)
 39                 {
 40                     case Stretch.Fill:
 41                         dx1 = bmp1.Width / ig1.ActualWidth;
 42                         dy1 = bmp1.Height / ig1.ActualHeight;
 43                         break;
 44                     case Stretch.None:
 45                         break;
 46                     case Stretch.Uniform:
 47                         if (ig1.ActualWidth > ig1.ActualHeight)
 48                         {
 49                             dx1 = bmp1.Width / ig1.ActualWidth;
 50                             dy1 = (bmp1.Height / bmp1.Width) * dx1;
 51                         }
 52                         else
 53                         {
 54                             dy1 = bmp1.Height / ig1.ActualHeight;
 55                             dx1 = (bmp1.Width / bmp1.Height) * dy1;
 56                         }
 57                         break;
 58                     case Stretch.UniformToFill:
 59                         if (ig1.ActualWidth > ig1.ActualHeight)
 60                         {
 61                             dx1 = bmp1.Width / ig1.ActualWidth;
 62                             dy1 = dx1;
 63                         }
 64                         else
 65                         {
 66                             dx1 = bmp1.Height / ig1.ActualHeight;
 67                             dy1 = dx1;
 68                         }
 69                         break;
 70                     default: break;
 71                 }
 72 
 73                 #endregion
 74 
 75                 int n = 0;
 76 
 77                 using (System.Drawing.Bitmap bmp2 = new System.Drawing.Bitmap(m2.PixelWidth, m2.PixelHeight, System.Drawing.Imaging.PixelFormat.Format32bppPArgb))
 78                 {
 79                     System.Drawing.Imaging.BitmapData data2 = bmp2.LockBits(
 80             new System.Drawing.Rectangle(System.Drawing.Point.Empty, bmp2.Size), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
 81                     m2.CopyPixels(Int32Rect.Empty, data2.Scan0, data2.Height * data2.Stride, data2.Stride); bmp2.UnlockBits(data2);
 82 
 83                     double dx2 = 1;
 84                     double dy2 = 1;
 85 
 86                     #region 获取缩放比例
 87 
 88                     switch (ig2.Stretch)
 89                     {
 90                         case Stretch.Fill:
 91                             dx2 = bmp2.Width / ig2.ActualWidth;
 92                             dy2 = bmp2.Height / ig2.ActualHeight;
 93                             break;
 94                         case Stretch.None:
 95                             break;
 96                         case Stretch.Uniform:
 97                             if (ig2.ActualWidth > ig2.ActualHeight)
 98                             {
 99                                 dx2 = bmp2.Width / ig2.ActualWidth;
100                                 dy2 = (bmp2.Height / bmp2.Width) * dx2;
101                             }
102                             else
103                             {
104                                 dy2 = bmp2.Height / ig2.ActualHeight;
105                                 dx2 = (bmp2.Width / bmp2.Height) * dy2;
106                             }
107                             break;
108                         case Stretch.UniformToFill:
109                             if (ig2.ActualWidth > ig2.ActualHeight)
110                             {
111                                 dx2 = bmp2.Width / ig2.ActualWidth;
112                                 dy2 = dx2;
113                             }
114                             else
115                             {
116                                 dx2 = bmp2.Height / ig2.ActualHeight;
117                                 dy2 = dx2;
118                             }
119                             break;
120                         default: break;
121                     }
122 
123                     #endregion
124 
125                     double XX1 = Canvas.GetLeft(ig1);
126                     double YY1 = Canvas.GetTop(ig1);
127                     double XX2 = Canvas.GetLeft(ig2);
128                     double YY2 = Canvas.GetTop(ig2);
129                     //double ig1Width = ig1.ActualWidth;
130                     //double ig1Height = ig1.ActualHeight;
131                     double ig1Width = containingRect1.Width;
132                     double ig1Height = containingRect1.Height;
133                     double ig2Width = ig2.ActualWidth;
134                     double ig2Height = ig2.ActualHeight;
135                     Stretch ig1ImageStretchType = ig1.Stretch;
136                     Stretch ig2ImageStretchType = ig2.Stretch;
137                     Boolean isInset = false;
138 
139                     #region 线程1
140 
141                     Thread t1 = new Thread(delegate()
142                     {
143                         for (int i = 0; i < ig1Width / 2; i++)
144                         {
145                             if (isInset)
146                             {
147                                 break;
148                             }
149                             for (int j = 0; j < ig1Height / 2; j++)
150                             {
151                                 if (isInset)
152                                 {
153                                     break;
154                                 }
155 
156                                 #region 判断图像1的点是否透明
157 
158                                 System.Windows.Point p1 = new System.Windows.Point(i + RectPoint.X - XX1, j + RectPoint.Y - YY1);
159                                 int x1 = -1;
160                                 int y1 = -1;
161                                 switch (ig1ImageStretchType)
162                                 {
163                                     case Stretch.Fill:
164                                         x1 = int.Parse((p1.X * dx1).ToString("F0"));
165                                         y1 = int.Parse((p1.Y * dy1).ToString("F0"));
166                                         break;
167                                     case Stretch.None:
168                                         x1 = int.Parse(p1.X.ToString("F0"));
169                                         y1 = int.Parse(p1.Y.ToString("F0"));
170                                         break;
171                                     case Stretch.Uniform:
172                                         x1 = int.Parse((p1.X * dx1).ToString("F0"));
173                                         y1 = int.Parse((p1.Y * dy1).ToString("F0"));
174                                         break;
175                                     case Stretch.UniformToFill:
176                                         x1 = int.Parse((p1.X * dx1).ToString("F0"));
177                                         y1 = int.Parse((p1.Y * dy1).ToString("F0"));
178                                         break;
179                                     default: break;
180                                 }
181                                 lock (bmp1)
182                                 {
183                                     if (x1 < 0 || y1 < 0 || x1 > bmp1.Width || y1 > bmp1.Height)
184                                     {
185                                         continue;
186                                     }
187                                     else
188                                     {
189                                         byte A = GetARGB(bmp1, x1, y1);
190                                         if ((int)A == 0)
191                                         {
192                                             continue;
193                                         }
194                                         else
195                                         {
196 
197                                         }
198                                     }
199                                 }
200 
201                                 #endregion
202 
203                                 #region 判断图像1的点相对于位置的图像2的点是否透明
204 
205                                 System.Windows.Point p2 = new System.Windows.Point(XX1 + p1.X - XX2, YY1 + p1.Y - YY2);
206                                 int x2 = -1;
207                                 int y2 = -1;
208                                 switch (ig2ImageStretchType)
209                                 {
210                                     case Stretch.Fill:
211                                         x2 = int.Parse((p2.X * dx2).ToString("F0"));
212                                         y2 = int.Parse((p2.Y * dy2).ToString("F0"));
213                                         break;
214                                     case Stretch.None:
215                                         x2 = int.Parse(p2.X.ToString("F0"));
216                                         y2 = int.Parse(p2.Y.ToString("F0"));
217                                         break;
218                                     case Stretch.Uniform:
219                                         x2 = int.Parse((p2.X * dx2).ToString("F0"));
220                                         y2 = int.Parse((p2.Y * dy2).ToString("F0"));
221                                         break;
222                                     case Stretch.UniformToFill:
223                                         x2 = int.Parse((p2.X * dx2).ToString("F0"));
224                                         y2 = int.Parse((p2.Y * dy2).ToString("F0"));
225                                         break;
226                                     default: break;
227                                 }
228                                 lock (bmp2)
229                                 {
230                                     if (x2 < 0 || y2 < 0 || x2 > bmp2.Width || y2 > bmp2.Height)
231                                     {
232                                         continue;
233                                     }
234                                     else
235                                     {
236                                         byte A = GetARGB(bmp2, x2, y2);
237                                         if ((int)A == 0)
238                                         {
239                                             continue;
240                                         }
241                                         else
242                                         {
243                                             isInset = true;
244                                             break;
245                                         }
246                                     }
247                                 }
248                                 #endregion
249 
250                             }
251                         }
252                         n = n + 1;
253                     });
254 
255                     #endregion
256 
257                     #region 线程2
258 
259                     Thread t2 = new Thread(delegate()
260                     {
261                         for (int i = int.Parse(ig1Width.ToString("F0")) - 1; i > int.Parse((ig1Width / 2).ToString("F0")); i--)
262                         {
263                             if (isInset)
264                             {
265                                 break;
266                             }
267                             for (int j = 0; j < ig1Height / 2; j++)
268                             {
269                                 if (isInset)
270                                 {
271                                     break;
272                                 }
273 
274                                 #region 判断图像1的点是否透明
275 
276                                 System.Windows.Point p1 = new System.Windows.Point(i + RectPoint.X - XX1, j + RectPoint.Y - YY1);
277                                 int x1 = -1;
278                                 int y1 = -1;
279                                 switch (ig1ImageStretchType)
280                                 {
281                                     case Stretch.Fill:
282                                         x1 = int.Parse((p1.X * dx1).ToString("F0"));
283                                         y1 = int.Parse((p1.Y * dy1).ToString("F0"));
284                                         break;
285                                     case Stretch.None:
286                                         x1 = int.Parse(p1.X.ToString("F0"));
287                                         y1 = int.Parse(p1.Y.ToString("F0"));
288                                         break;
289                                     case Stretch.Uniform:
290                                         x1 = int.Parse((p1.X * dx1).ToString("F0"));
291                                         y1 = int.Parse((p1.Y * dy1).ToString("F0"));
292                                         break;
293                                     case Stretch.UniformToFill:
294                                         x1 = int.Parse((p1.X * dx1).ToString("F0"));
295                                         y1 = int.Parse((p1.Y * dy1).ToString("F0"));
296                                         break;
297                                     default: break;
298                                 }
299                                 lock (bmp1)
300                                 {
301                                     if (x1 < 0 || y1 < 0 || x1 > bmp1.Width || y1 > bmp1.Height)
302                                     {
303                                         continue;
304                                     }
305                                     else
306                                     {
307                                         byte A = GetARGB(bmp1, x1, y1);
308                                         if ((int)A == 0)
309                                         {
310                                             continue;
311                                         }
312                                         else
313                                         {
314 
315                                         }
316                                     }
317                                 }
318 
319                                 #endregion
320 
321                                 #region 判断图像1的点相对于位置的图像2的点是否透明
322 
323                                 System.Windows.Point p2 = new System.Windows.Point(XX1 + p1.X - XX2, YY1 + p1.Y - YY2);
324                                 int x2 = -1;
325                                 int y2 = -1;
326                                 switch (ig2ImageStretchType)
327                                 {
328                                     case Stretch.Fill:
329                                         x2 = int.Parse((p2.X * dx2).ToString("F0"));
330                                         y2 = int.Parse((p2.Y * dy2).ToString("F0"));
331                                         break;
332                                     case Stretch.None:
333                                         x2 = int.Parse(p2.X.ToString("F0"));
334                                         y2 = int.Parse(p2.Y.ToString("F0"));
335                                         break;
336                                     case Stretch.Uniform:
337                                         x2 = int.Parse((p2.X * dx2).ToString("F0"));
338                                         y2 = int.Parse((p2.Y * dy2).ToString("F0"));
339                                         break;
340                                     case Stretch.UniformToFill:
341                                         x2 = int.Parse((p2.X * dx2).ToString("F0"));
342                                         y2 = int.Parse((p2.Y * dy2).ToString("F0"));
343                                         break;
344                                     default: break;
345                                 }
346                                 lock (bmp2)
347                                 {
348                                     if (x2 < 0 || y2 < 0 || x2 > bmp2.Width || y2 > bmp2.Height)
349                                     {
350                                         continue;
351                                     }
352                                     else
353                                     {
354                                         byte A = GetARGB(bmp2, x2, y2);
355                                         if ((int)A == 0)
356                                         {
357                                             continue;
358                                         }
359                                         else
360                                         {
361                                             isInset = true;
362                                             break;
363                                         }
364                                     }
365                                 }
366                                 #endregion
367 
368                             }
369                         }
370                         n = n + 1;
371                     });
372 
373                     #endregion
374 
375                     #region 线程3
376 
377                     Thread t3 = new Thread(delegate()
378                     {
379                         for (int i = 0; i < ig1Width / 2; i++)
380                         {
381                             if (isInset)
382                             {
383                                 break;
384                             }
385                             for (int j = int.Parse(ig1Height.ToString("F0")) - 1; j > int.Parse((ig1Height / 2).ToString("F0")); j--)
386                             {
387                                 if (isInset)
388                                 {
389                                     break;
390                                 }
391 
392                                 #region 判断图像1的点是否透明
393 
394                                 System.Windows.Point p1 = new System.Windows.Point(i + RectPoint.X - XX1, j + RectPoint.Y - YY1);
395                                 int x1 = -1;
396                                 int y1 = -1;
397                                 switch (ig1ImageStretchType)
398                                 {
399                                     case Stretch.Fill:
400                                         x1 = int.Parse((p1.X * dx1).ToString("F0"));
401                                         y1 = int.Parse((p1.Y * dy1).ToString("F0"));
402                                         break;
403                                     case Stretch.None:
404                                         x1 = int.Parse(p1.X.ToString("F0"));
405                                         y1 = int.Parse(p1.Y.ToString("F0"));
406                                         break;
407                                     case Stretch.Uniform:
408                                         x1 = int.Parse((p1.X * dx1).ToString("F0"));
409                                         y1 = int.Parse((p1.Y * dy1).ToString("F0"));
410                                         break;
411                                     case Stretch.UniformToFill:
412                                         x1 = int.Parse((p1.X * dx1).ToString("F0"));
413                                         y1 = int.Parse((p1.Y * dy1).ToString("F0"));
414                                         break;
415                                     default: break;
416                                 }
417                                 lock (bmp1)
418                                 {
419                                     if (x1 < 0 || y1 < 0 || x1 > bmp1.Width || y1 > bmp1.Height)
420                                     {
421                                         continue;
422                                     }
423                                     else
424                                     {
425                                         byte A = GetARGB(bmp1, x1, y1);
426                                         if ((int)A == 0)
427                                         {
428                                             continue;
429                                         }
430                                         else
431                                         {
432 
433                                         }
434                                     }
435                                 }
436 
437                                 #endregion
438 
439                                 #region 判断图像1的点相对于位置的图像2的点是否透明
440 
441                                 System.Windows.Point p2 = new System.Windows.Point(XX1 + p1.X - XX2, YY1 + p1.Y - YY2);
442                                 int x2 = -1;
443                                 int y2 = -1;
444                                 switch (ig2ImageStretchType)
445                                 {
446                                     case Stretch.Fill:
447                                         x2 = int.Parse((p2.X * dx2).ToString("F0"));
448                                         y2 = int.Parse((p2.Y * dy2).ToString("F0"));
449                                         break;
450                                     case Stretch.None:
451                                         x2 = int.Parse(p2.X.ToString("F0"));
452                                         y2 = int.Parse(p2.Y.ToString("F0"));
453                                         break;
454                                     case Stretch.Uniform:
455                                         x2 = int.Parse((p2.X * dx2).ToString("F0"));
456                                         y2 = int.Parse((p2.Y * dy2).ToString("F0"));
457                                         break;
458                                     case Stretch.UniformToFill:
459                                         x2 = int.Parse((p2.X * dx2).ToString("F0"));
460                                         y2 = int.Parse((p2.Y * dy2).ToString("F0"));
461                                         break;
462                                     default: break;
463                                 }
464                                 lock (bmp2)
465                                 {
466                                     if (x2 < 0 || y2 < 0 || x2 > bmp2.Width || y2 > bmp2.Height)
467                                     {
468                                         continue;
469                                     }
470                                     else
471                                     {
472                                         byte A = GetARGB(bmp2, x2, y2);
473                                         if ((int)A == 0)
474                                         {
475                                             continue;
476                                         }
477                                         else
478                                         {
479                                             isInset = true;
480                                             break;
481                                         }
482                                     }
483                                 }
484                                 #endregion
485                             }
486                         }
487                         n = n + 1;
488                     });
489 
490                     #endregion
491 
492                     #region 线程4
493 
494                     Thread t4 = new Thread(delegate()
495                     {
496                         for (int i = int.Parse(ig1Width.ToString("F0")) - 1; i > int.Parse((ig1Width / 2).ToString("F0")); i--)
497                         {
498                             if (isInset)
499                             {
500                                 break;
501                             }
502                             for (int j = int.Parse(ig1Height.ToString("F0")) - 1; j > int.Parse((ig1Height / 2).ToString("F0")); j--)
503                             {
504                                 if (isInset)
505                                 {
506                                     break;
507                                 }
508                                 #region 判断图像1的点是否透明
509 
510                                 System.Windows.Point p1 = new System.Windows.Point(i + RectPoint.X - XX1, j + RectPoint.Y - YY1);
511                                 int x1 = -1;
512                                 int y1 = -1;
513                                 switch (ig1ImageStretchType)
514                                 {
515                                     case Stretch.Fill:
516                                         x1 = int.Parse((p1.X * dx1).ToString("F0"));
517                                         y1 = int.Parse((p1.Y * dy1).ToString("F0"));
518                                         break;
519                                     case Stretch.None:
520                                         x1 = int.Parse(p1.X.ToString("F0"));
521                                         y1 = int.Parse(p1.Y.ToString("F0"));
522                                         break;
523                                     case Stretch.Uniform:
524                                         x1 = int.Parse((p1.X * dx1).ToString("F0"));
525                                         y1 = int.Parse((p1.Y * dy1).ToString("F0"));
526                                         break;
527                                     case Stretch.UniformToFill:
528                                         x1 = int.Parse((p1.X * dx1).ToString("F0"));
529                                         y1 = int.Parse((p1.Y * dy1).ToString("F0"));
530                                         break;
531                                     default: break;
532                                 }
533                                 lock (bmp1)
534                                 {
535                                     if (x1 < 0 || y1 < 0 || x1 > bmp1.Width || y1 > bmp1.Height)
536                                     {
537                                         continue;
538                                     }
539                                     else
540                                     {
541                                         byte A = GetARGB(bmp1, x1, y1);
542                                         if ((int)A == 0)
543                                         {
544                                             continue;
545                                         }
546                                         else
547                                         {
548 
549                                         }
550                                     }
551                                 }
552 
553                                 #endregion
554 
555                                 #region 判断图像1的点相对于位置的图像2的点是否透明
556 
557                                 System.Windows.Point p2 = new System.Windows.Point(XX1 + p1.X - XX2, YY1 + p1.Y - YY2);
558                                 int x2 = -1;
559                                 int y2 = -1;
560                                 switch (ig2ImageStretchType)
561                                 {
562                                     case Stretch.Fill:
563                                         x2 = int.Parse((p2.X * dx2).ToString("F0"));
564                                         y2 = int.Parse((p2.Y * dy2).ToString("F0"));
565                                         break;
566                                     case Stretch.None:
567                                         x2 = int.Parse(p2.X.ToString("F0"));
568                                         y2 = int.Parse(p2.Y.ToString("F0"));
569                                         break;
570                                     case Stretch.Uniform:
571                                         x2 = int.Parse((p2.X * dx2).ToString("F0"));
572                                         y2 = int.Parse((p2.Y * dy2).ToString("F0"));
573                                         break;
574                                     case Stretch.UniformToFill:
575                                         x2 = int.Parse((p2.X * dx2).ToString("F0"));
576                                         y2 = int.Parse((p2.Y * dy2).ToString("F0"));
577                                         break;
578                                     default: break;
579                                 }
580                                 lock (bmp2)
581                                 {
582                                     if (x2 < 0 || y2 < 0 || x2 > bmp2.Width || y2 > bmp2.Height)
583                                     {
584                                         continue;
585                                     }
586                                     else
587                                     {
588                                         byte A = GetARGB(bmp2, x2, y2);
589                                         if ((int)A == 0)
590                                         {
591                                             continue;
592                                         }
593                                         else
594                                         {
595                                             isInset = true;
596                                             break;
597                                         }
598                                     }
599                                 }
600                                 #endregion
601                             }
602                         }
603                         n = n + 1;
604                     });
605 
606                     #endregion
607 
608                     t1.Start();
609                     t2.Start();
610                     t3.Start();
611                     t4.Start();
612                     while (n != 4)
613                     {
614                         Thread.Sleep(1);
615                     }
616                     return isInset;
617                 }
618 
619                 #endregion
620 
621             }
622         }
View Code

这个算法我用了连个128X128的图片放到两个200X200的Image中

正常利用VS调试每次判定在150ms左右 不调试直接运行大概在3~10ms之间

电脑配置CPU G1840 内存4G 效率还可以 喜欢的朋友可以参考一下

欢迎大家留下脚印~

本文版权归本作者所有 未经允许禁止用于商业目的 转载请注明出处

以上是关于WPF判断两个PNG图片是否碰撞的主要内容,如果未能解决你的问题,请参考以下文章

Java游戏中的圆形碰撞检测

怎样使用Alpha通道使png图片透明

H5中优化碰撞检测

H5中优化碰撞检测

html [Circle Collision]通过判断任意两个圆形的圆心距离是否小于两圆半径之和,若小于则为碰撞#JavaScript #HTML

wpf 获取image控件的图片并保存