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 }
这个算法我用了连个128X128的图片放到两个200X200的Image中
正常利用VS调试每次判定在150ms左右 不调试直接运行大概在3~10ms之间
电脑配置CPU G1840 内存4G 效率还可以 喜欢的朋友可以参考一下
欢迎大家留下脚印~
本文版权归本作者所有 未经允许禁止用于商业目的 转载请注明出处
以上是关于WPF判断两个PNG图片是否碰撞的主要内容,如果未能解决你的问题,请参考以下文章
html [Circle Collision]通过判断任意两个圆形的圆心距离是否小于两圆半径之和,若小于则为碰撞#JavaScript #HTML