Prior to Silverlight 2.0 Beta 1, there was no method provided in the framework for determining if two UI elements were colliding. So if you wanted collision testing, you had to pretty much brew up your own. But there is now a HitTest method provided on the UIElement class. This method returns a list of elements that intersect with a Point or Rect. Not particularly helpful out of the box, and also not a very fast operation, but using this new HitTest method we can do some fair collision detection.
[TRY THE DEMO] [DOWNLOAD SOURCE]
If you try the demo above (Silverlight 2 Beta 1 Required), you can use the mouse to move the ship around the asteroid. Notice that a collision is only detected when the ship's outer path element collides with the asteroid's path element.
This was done using the method below, which can be used to determine if two UI Elements are colliding. Remember that the HitTest method is very slow so we always want to do a quick Rectangle Intersect collision test first before doing a per-pixel HitTest. Once intersection rectangle is found, the code simply loops through pixel-by-pixel to see if both elements in question share a HitTest on the same x,y pixel…
private bool CheckCollision(FrameworkElement control1, FrameworkElement controlElem1, FrameworkElement control2, FrameworkElement controlElem2)
{
// first see if sprite rectangles collide
Rect rect1 = UserControlBounds(control1);
Rect rect2 = UserControlBounds(control2);
rect1.Intersect(rect2);
if (rect1 == Rect.Empty)
{
// no collision - GET OUT!
return false;
}
else
{
bool bCollision = false;
Point ptCheck = new Point();
// now we do a more accurate pixel hit test
for (int x = Convert.ToInt32(rect1.X); x < Convert.ToInt32(rect1.X + rect1.Width); x++)
{
for (int y = Convert.ToInt32(rect1.Y); y < Convert.ToInt32(rect1.Y + rect1.Height); y++)
{
ptCheck.X = x;
ptCheck.Y = y;
List<UIElement> hits = (List<UIElement>)control1.HitTest(ptCheck);
if (hits.Contains(controlElem1))
{
// we have a hit on the first control elem,
// now see if the second elem has a similar hit
List<UIElement> hits2 = (List<UIElement>)control2.HitTest(ptCheck);
if (hits2.Contains(controlElem2))
{
bCollision = true;
break;
}
}
}
if (bCollision) break;
}
return bCollision;
}
}