silverlight 碰撞检测

在游戏开发中其中一个常用的功能就是判断两个元素是否有相交在一起,让我们的游戏元素有一个与现实世界更相似的环境。

以下是一个可以判断两个FrameworkElement是否有碰撞到的实现方法:

 1:  private bool CheckCollision(FrameworkElement control1, FrameworkElement controlElem1, FrameworkElement control2, FrameworkElement controlElem2)
 2:  {
 3:      // first see if sprite rectangles collide
 4:      Rect rect1 = UserControlBounds(control1);
 5:      Rect rect2 = UserControlBounds(control2);
 6:  
 7:      rect1.Intersect(rect2);
 8:      if (rect1 == Rect.Empty)
 9:      {
10:          // no collision - GET OUT!
11:          return false;
12:      }
13:      else
14:      {
15:          bool bCollision = false;
16:          Point ptCheck = new Point();
17:  
18:          // NOTE that creating the writeablebitmap is a bit intense
19:          // so we will do this once and store results in Tag property
20:          // in a real game, you might abstract this into a Sprite class.
21:          if (controlElem1 is Image)
22:              controlElem1.Tag = GetWriteableBitmap(control1);
23:  
24:          if (controlElem2 is Image)
25:              controlElem2.Tag = GetWriteableBitmap(control2);
26:  
27:          // now we do a more accurate pixel hit test
28:          for (int x = Convert.ToInt32(rect1.X); x < Convert.ToInt32(rect1.X + rect1.Width); x++)
29:          {
30:              for (int y = Convert.ToInt32(rect1.Y); y < Convert.ToInt32(rect1.Y + rect1.Height); y++)
31:              {
32:                  ptCheck.X = x;
33:                  ptCheck.Y = y;
34:  
35:  
36:                  if (CheckCollisionPoint(ptCheck, control1, controlElem1))
37:                      if (CheckCollisionPoint(ptCheck, control2, controlElem2))
38:                      {
39:                          bCollision = true;
40:                          break;
41:                      }
42:  
43:              }
44:              if (bCollision) break;
45:          }
46:          return bCollision;
47:      }
48:  }
49:  
50:  public bool CheckCollisionPoint(Point pt, FrameworkElement control, FrameworkElement controlElem)
51:  {
52:      if (controlElem is Image)
53:      {
54:          // NOTE that we saved the WB in the Tag object for performance.
55:          // in a real app, you might abstract this in your sprite class.
56:          WriteableBitmap wb = controlElem.Tag as WriteableBitmap;
57:  
58:          int width = wb.PixelWidth;
59:          int height = wb.PixelHeight;
60:  
61:          double offSetX = Convert.ToDouble(control.GetValue(Canvas.LeftProperty));
62:          double offSetY = Convert.ToDouble(control.GetValue(Canvas.TopProperty));
63:  
64:          pt.X = pt.X - offSetX;
65:          pt.Y = pt.Y - offSetY;
66:  
67:          int offset = Convert.ToInt32((width * pt.Y) + pt.X);
68:  
69:          return (wb.Pixels[offset] != 0);
70:      }
71:      else
72:      {
73:          List<UIElement> hits = System.Windows.Media.VisualTreeHelper.FindElementsInHostCoordinates(pt, controlElem) as List<UIElement>;
74:          return (hits.Contains(controlElem));
75:      }
76:  }
77:  
78:  private WriteableBitmap GetWriteableBitmap(FrameworkElement control)
79:  {
80:      WriteableBitmap wb = new WriteableBitmap((int)control.Width, (int)control.Height); ;
81:      wb.Render(control, new TranslateTransform());
82:      wb.Invalidate();
83:  
84:      return wb;
85:  }
86:  
87:  public Rect UserControlBounds(FrameworkElement control)
88:  {
89:      Point ptTopLeft = new Point(Convert.ToDouble(control.GetValue(Canvas.LeftProperty)), Convert.ToDouble(control.GetValue(Canvas.TopProperty)));
90:      Point ptBottomRight = new Point(Convert.ToDouble(control.GetValue(Canvas.LeftProperty)) + control.Width, Convert.ToDouble(control.GetValue(Canvas.TopProperty)) + control.Height);
91:  
92:      return new Rect(ptTopLeft, ptBottomRight);
93:  }
94:  

检测:

1:  if (CheckCollision(sp1, sp1.ShipShell, sp2, sp2.ShipShell))
2:  {
3:      tb.Text = "true";
4:  }
5:  else
6:  {
7:      tb.Text = "false";
8:  }
posted @ 2012-12-10 09:08  黎东海  阅读(210)  评论(0编辑  收藏  举报