SpriteHand
Module Border
  More Polygon Physics with Silverlight
Module Border
Location: BlogsAndy's Blog    
Posted by: host 7/17/2008 2:28 PM

I’ve souped up my previous demo on Polygon Physics using Silverlight and Farseer to include two improvements. First, I’ve added a utility function to create an approximate Farseer Polygon Geometry from any Silverlight Path object. Also, I’ve added the ability to manipulate the polygons using the mouse (turns out this is pretty easy thanks to Farseer). In this blog post, I’ll explain how I made these enhancements.

[TRY THE DEMO]       [DOWNLOAD THE SOURCE]

 

To begin, if you are new to Farseer Physics and Silverlight, you should start with my first post on Polygon Physics.

Creating a Farseer Polygon Geometry based on a Path

In the demo app, if you type out any letters (A-Z) on the keyboard, then you will see a demo of Path objects being translated to Polygon Physics objects. In the Silverlight Project, these Path objects are pulled from the ucAlphabet.xaml user control.

There is an unfortunate problem in Silverlight 2 Beta 2 (not sure if this will be resolved by release time) with getting the geometry information on a Path object. So let’s say you design a Path using Expression Blend:

<Path x:Name="pathTest" Height="65" HorizontalAlignment="Left" Margin="78.5,57.5,0,0" VerticalAlignment="Top" Width="83" Data="M98,89 L79,122 L117,119 L150,108 L161,58 L102,58 z" Fill="#FFFFFFFF" Stretch="Fill" Stroke="#FF000000"/>


…and then you later want to manipulate that Path’s geometry using code –

foreach (PathFigure figure in (pathTest.Data as PathGeometry).Figures)

{

    // this won't work in Silverlight 2 Beta 2

    // the Figures collection is always empty!

}


…you really can’t do the manipulation in code because the Path.Data property does not get filled.

So, we need another method of getting the Path’s shape so that we can hand it off to Farseer. One way we could do this is by translating the Path “mini-language” which defines the shape. So we could translate this part of the XAML for the Path:

Data="M98,89 L79,122 L117,119 L150,108 L161,58 L102,58 z"

I actually think this would be an ideal approach, but it’s not the one I took. Instead, I used the HitTest method to “scan” the Path for its approximate shape. I did this with a series of loops which scans each side of the Path and tests each x,y point for a hit. If the HitTest succeeds on a point, then I add that point into a list which defines the overall shape. I then give this list of points depicting the shape over to Farseer to define the Polygon Geometry.

Below is an excerpt from the method Utils.GetPointsForPath which scans the left side of the Path to get it’s outline:

// left side

for (double y = top; y < top + height; y++)

{

    for (double x = left; x < left + width; x++)

    {

        Point ptTest = new Point(x,y);

        List<UIElement> hits = path.HitTest(ptTest) as List<UIElement>;

        if (hits.Contains(path))

        {

            Point ptHit = new Point(x / scaleX, y / scaleY);

            outline.Add(ptHit);

            break;

        }

 

    }

}

 

I simply repeat this for the bottom, right, and top sides and then I have a list of points representing the approximate outline of the Path.

Manipulating Polygons with the Mouse

This is almost a freebie and can be nearly copy/pasted from the original Silverlight/Farseer demos ported by Bill Reiss. To allow the user to grab onto a Farseer object and move it around the screen, we need to do three basic steps:

1. In the MouseDown event for the polygon, we keep track of the polygon (“sprite”) that was clicked and create a Fixed Linear Spring at the clicked point.

void sprite_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)

{

    Vector2 point = new Vector2((float)(e.GetPosition(_parentCanvas).X), (float)(e.GetPosition(_parentCanvas).Y));

    _pickedSprite = (sender as SpriteBase);

    _pickedSprite.CaptureMouse();

    if (_pickedSprite != null)

    {

        _mousePickSpring = ControllerFactory.Instance.CreateFixedLinearSpring(_physicsSimulator, _pickedSprite.BodyObject, _pickedSprite.BodyObject.GetLocalPosition(point), point, 10, 5);

        e.Handled = true;

    }

}

 

2. In the MouseMove event for the polygon, we adjust the attached point for the Fixed Linear Spring to the mouse move point.

void sprite_MouseMove(object sender, MouseEventArgs e)

{

    if (_mousePickSpring != null)

    {

        Vector2 point = new Vector2((float)(e.GetPosition(_parentCanvas).X), (float)(e.GetPosition(_parentCanvas).Y));

        _mousePickSpring.WorldAttachPoint = point;

        e.Handled = true;

    }

}

 

3. In the MouseUp event for the polygon, we dispose of the Fixed Linear Spring.

void sprite_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)

{

    if (_mousePickSpring != null && _mousePickSpring.IsDisposed == false)

    {

        _mousePickSpring.Dispose();

        _mousePickSpring = null;

        _pickedSprite.ReleaseMouseCapture();

        e.Handled = true;

    }

}

 

I also embellished with a Line showing the drag direction of the Spring from the Polygon.

Summary

Note that the “HitTest for Path Outline” method is only giving an approximate Polygon outlining the shape of the Path, but it is pretty close! I think with some further tweaks to the Utils.GetPointsForPath method, it could get even closer.

Permalink |  Trackback

Comments (3)   Add Comment
Re: More Polygon Physics with Silverlight    By Anonymous on 7/18/2008 3:58 PM
Andy,
Another work around for getting at the Path geometry of objects created in Blend is to force Blend to render the full object tree for the Path rather than use the mini-language. If the Path is rendered long-form, you can get access to it and all it's sub-objects through code.

By default Blend does not do this and there is no setting to force Blend to render the complete XAML. I did, however, find a way to "trick" Blend into rendering the full XAML for a Path.

If you create a bogus storyboard on the Path and animate any vertice by at least by 1 pixel, Blend will render the Path's XAML in it's long-form (no mini-language).

This then will allow you to access the Path and all it's sub-objects in code back in Visual Studio. It's a hack, but its been working well for me.

I posted this to the Blend forum and asked if they could add a simple setting to Blend that would force all xaml to be render in long-form. Nobody responded as far as I know.

-Jeff Weber

Re: More Polygon Physics with Silverlight    By Anonymous on 7/19/2008 8:32 AM
That's a great tip Jeff, Thanks!

-Andy

Re: More Polygon Physics with Silverlight    By Anonymous on 7/23/2008 10:51 AM
Andy,

I threw together a little toy based on Farseer and your examples...

http://www.anatone.net/fallout

You can draw on the screen and it creates Farseer static polygon geometry. Then you can hover the mouse over the button and marbles will drop. The slider bar controls the frequency of the marbles. Left is faster, right is slower.

Thanks for the demos and code...

Timothy Russell


Title:
Comment:
Add Comment   Cancel 
Module Border Module Border
Module Border
  Blog_List
Module Border
Module Border Module Border
Module Border
  Subscribe
Module Border

RSS

Module Border Module Border
Module Border
  Diversions
Module Border

DESTROY ALL INVADERS
A scrolling shooter game where the objective is to destroy the invading UFO's flying over a neighborhood of your choosing. Imagery provided by Microsoft Virtual Earth. Created using Silverlight 2.
PLAY IT

INFO AND CODE



SORT THE FOOBARS
A game where you need to sort the good foobars from the bad ones. Created using Silverlight 2 and the Farseer Physics engine.
PLAY IT

MORE INFO



POLYGON PHYSICS DEMO
A demo showing polygon physics where the user draws physics objects with the mouse. Created using Silverlight 2 and the Farseer Physics engine.
PLAY IT

MORE INFO



SILVERLIGHT ROCKS!
Destroy the asteroids before they destroy your ship! Created using Silverlight 2.
PLAY IT

INFO AND CODE



FISH GAME
A simple game of harpoon-the-fish. Written using the AJAX Sprite Toolkit.
PLAY IT

INFO AND CODE

Module Border Module Border
Module Border
  Search_Blog
Module Border
Module Border Module Border
Module Border
  Blog_Archive
Module Border
Module Border Module Border
Copyright (c) 2008 andy.beaulieu.com - Login