UPDATE 3/5/2008: Now available for Silverlight 2 Beta 1.
In a previous post, I showed how we can quickly get started using Silverlight to create some great Physics games and simulations using the Farseer Physics Engine. In this post, I am going to show some more advanced physics effects using Farseer's Polygon Geometry.

We'll be creating kind of a "Sketch Pad on Steroids" where what the user draws becomes a physics object and "falls" to the ground. I can think of about a dozen game ideas you could implement with these techniques, including something like the jaw dropping Crayon Physics Deluxe.
SEE THE SAMPLE IN ACTION
DOWNLOAD THE SOURCE CODE
Drawing a Path Using the Mouse
First let's look at how we can capture a series of x,y points that the user draws. If you look at Page.xaml.cs, you can see that when the user moves the mouse, we record all of their movements in a _polygonPoints, which is a Generic List of Point objects:
void Page_MouseMove(object sender, MouseEventArgs e)
{
if (_drawActive)
{
_polygonPoints.Add(e.GetPosition(_parentCanvas));
// draw the polygon
if (_TempPolygonPath != null)
{
_parentCanvas.Children.Remove(_TempPolygonPath);
_TempPolygonPath = null;
}
_TempPolygonPath = Utils.CreatePathFromPoints(_polygonPoints, "tempPolygonPath");
_parentCanvas.Children.Add(_TempPolygonPath);
}
}
We also call a function, Utils.CreatePathFromPoints, which creates a Path object based on the points, and add the Path to the page's Canvas:
public static Path CreatePathFromPoints(List<Point> points, string name)
{
Path path = new Path();
path.Stroke = new SolidColorBrush(Colors.Magenta);
path.StrokeThickness = 1;
path.Fill = new SolidColorBrush(Colors.Transparent);
PathGeometry pathGeom = new PathGeometry();
PathFigureCollection figures = new PathFigureCollection();
pathGeom.Figures = figures;
PathFigure figure = new PathFigure();
figure.StartPoint = new Point((double)points[0].X, (double)points[0].Y);
figure.Segments = new PathSegmentCollection();
pathGeom.Figures.Add(figure);
foreach (Point point in points)
{
LineSegment line = new LineSegment() { Point = new Point((double)point.X, (double)point.Y) };
figure.Segments.Add(line);
}
path.Data = pathGeom;
return path;
}
...So that gives us a basic sketch pad, with all of the points stored in a buffer. But now we need to change that collection of points into a Physics object.
Creating our Polygon Physics
Remember to take a peek at my previous introductory post on using Farseer Physics with Silverlight, as I'll be skipping the basics. If you remember, we used a SpriteBase class to wrap the details of our physics objects. In this demo, I created a ucPolygon class which you can think of as a sprite - it just happens to be one that the user draws out.
Farseer differentiates between Bodies, which are the actual physics bodies that bounce and fly around, and Geometries, which are the shapes of the Body used for collision detection.
So we first need to define the shape of our physics geometry using a Vertices collection. Note that, in Farseer, coordinate points need to be based on 0,0 being at the geometry's center, so we will need to translate our drawn points on the Path/Canvas to the Geometry object. Take a peek at ucPolygon.xaml.cs, which creates the vertices collection:
// create the physics body
fsc.Vertices vertices = new fsc.Vertices();
foreach (Point point in points)
{
// note vertices are based on 0,0 at center of body
double x, y;
// first we need to remove the offset position of the drawn shape on the main canvas
x = (Convert.ToDouble(point.X) - position.X);
y = (Convert.ToDouble(point.Y) - position.Y);
// we may need to offset position to get the point out of the negative
x = x + tweakX;
y = y + tweakY;
// we need to make points relative to origin (center) of object
x = x - centerX;
y = y - centerY;
vertices.Add(new Vector2((float)x, (float)y));
}
We can then create our polygon's Body by calling CreateBody and passing in an instance of the Physics Simulator, the Mass of the object, and the moment of intertia. Note that there is a handy utility function on the Vertices class to calculate moment of inertia for us:
BodyObject = BodyFactory.Instance.CreateBody(physicsSim, 0.5f, vertices.CalculateMomentOfInertia());
Finally, we create the actual Geometry object by calling CreatePolygonGeom and passing the simulator, body object, vertices collection, and collsion grid cell size (you can tweak the collision grid if necessary for your application, but I found zero to be adequate for this demo).
fsc.Geom polygonGeometry = fsc.GeomFactory.Instance.CreatePolygonGeom(physicsSim, BodyObject, vertices, 0);
There is also a useful SetDebug method on the ucPolygon class, which will draw the center and boundary of the polygon. This was very useful during development as sometimes the Body and Geometry can get out of sync if you're not careful.
Conclusion and More Info
I am really impressed with how easily effects can be created using Silverlight's powerful UI and Farseer's friendly API. I can foresee some really great browser-based games in Silverlight's future!
A shout back to Cameron Albert who used and credited my SpriteBase Class and returned the favor with some helpful code on creating Path Geometries with Farseer! And to Jeff Weber and Michael Brooks who helped me with troubleshooting on the Farseer Forums.
One last note, debugging the collision behavior in Farseer can be quite frustrating until you get your arms around it. There is a good introductory document that can help you out with the specifics.