 |
|
|
|
Improved HitTest Method for Silverlight 3
|
|
|
 |
|
Location: Blogs Andy's Blog |
|
| Posted by: host |
7/10/2009 8:24 AM |
With the new Silverlight 3 WriteableBitmap class, it’s possible to do pixel-perfect collision detection (a “HitTest”) on bitmap (raster) images. In a previous blog post, I showed how we can do a HitTest on Vector graphics in Silverlight 2. In this blog post, we’ll enhance the collision detection to handle BOTH Vector graphics and Raster graphics in Silverlight 3.
VIEW THE DEMO
DOWNLOAD THE SOURCE
Looking at the demo code, one of the main routines is the CheckCollisionPoint class, which does a HitTest on a UI Element at a specific Point. If the element is an Image, then a WriteableBitmap object is used to check the specific pixel point (this WriteableBitmap is created in the CheckCollision method, shown later.). If the element is not an image, then we assume it is Vector based and we use the VisualTreeHelper class for a hit test:
public bool CheckCollisionPoint(Point pt, FrameworkElement control, FrameworkElement controlElem)
{
if (controlElem is Image)
{
// NOTE that we saved the WB in the Tag object for performance.
// in a real app, you would abstract this in your sprite class.
WriteableBitmap wb = controlElem.Tag as WriteableBitmap;
int width = wb.PixelWidth;
int height = wb.PixelHeight;
double offSetX = Convert.ToDouble(control.GetValue(Canvas.LeftProperty));
double offSetY = Convert.ToDouble(control.GetValue(Canvas.TopProperty));
pt.X = pt.X - offSetX;
pt.Y = pt.Y - offSetY;
int offset = Convert.ToInt32((width * pt.Y) + pt.X);
return (wb.Pixels[offset] != 0);
}
else
{
List<UIElement> hits = System.Windows.Media.VisualTreeHelper.FindElementsInHostCoordinates(pt, controlElem) as List<UIElement>;
return (hits.Contains(controlElem));
}
} |
The CheckCollisionPoint method is used by the CheckCollision method, which checks for a collision between two UI elements. Note that we always want to do a quick Rect.Intersect test on the bounds of the elements before doing the slower per-pixel Hit Test. This method also creates the WriteableBitmap and stores it in the Tag property (you may want to abstract this into a Sprite class in a real application):
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();
// NOTE that creating the writeablebitmap is a bit intense
// so we will do this once and store results in Tag property
// in a real game, you might abstract this into a Sprite class.
if (controlElem1 is Image)
controlElem1.Tag = GetWriteableBitmap(control1);
if (controlElem2 is Image)
controlElem2.Tag = GetWriteableBitmap(control2);
// 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;
if (CheckCollisionPoint(ptCheck, control1, controlElem1))
if (CheckCollisionPoint(ptCheck, control2, controlElem2))
{
bCollision = true;
break;
}
}
if (bCollision) break;
}
return bCollision;
}
} |
A quick note about performance: This method provides a simple way of getting pixel-perfect collision detection in Silverlight 3. But if you have a lot of elements that are colliding simultaneously (without being destroyed), this may not perform well. Also, high velocity objects could pass through each other.
|
|
| Permalink |
Trackback |
Comments (4)
Add Comment
|
andy.beaulieu.com > Home - Improved HitTest Method for Silverlight 3
|
By TrackBack on
7/11/2009 8:00 AM
|
Thank you for submitting this cool story - Trackback from NewsPeeps # NewsPeeps
|
|
|
Re: Improved HitTest Method for Silverlight 3
|
By Anonymous on
7/12/2009 1:44 PM
|
|
Good Work, that goes for You and the SL team.
|
|
|
Merry X-Mas Silverlight 3
|
By TrackBack on
12/24/2009 12:40 PM
|
Merry X-Mas Silverlight 3 # Wesly van Zoen
|
|
|
Re: Improved HitTest Method for Silverlight 3
|
By Anonymous on
1/23/2010 3:42 AM
|
|
Thanks a lot man .... amazing work you have here. Thanks for sharing.
|
|
|
|
 |
|
 |
|
|