SpriteHand
Module Border
  Getting Started with Farseer Physics and Silverlight
Module Border
Location: BlogsAndy's Blog    
Posted by: host 12/21/2007 8:28 PM

I’m sure some of us may be taking a little break for the holidays, and might even get a few hours of coding time to sip from the firehose of technologies streaming out of Microsoft.

 

Might I recommend indulging in a little Silverlight game programming? J

 

To help you along, and as my gift for the holidays, I have put together an introduction to using Silverlight and Farseer Physics in perfect harmony.

 

Happy holidays!

 

Overview

The Farseer Physics Engine was created by Jeff Weber and later ported to Silverlight by Bill Reiss. Game programming with Silverlight is fun enough, but when you combine it with this easy to use physics engine, it’s almost as much fun to create games as play them!


In this walkthrough, I will be using the familiar “foobar” sprites from the Sort the Foobars game I posted last month.

 

DOWNLOAD THE SOURCE CODE

 

SEE THE SAMPLE IN ACTION

 

The Ingredients

First, let’s cover what you will need for this walkthrough:

 

  1. Visual Studio 2008. I am using the Professional Edition, but you should be fine with Express as well.

  2. Microsoft Silverlight 1.1 Tools Alpha for Visual Studio 2008. This provides the silverlight templates for VS.

  3. Microsoft Silverlight 1.1 Alpha Refresh. This is the actual Silverlight plug-in, in case you have not already installed it.

  4. (Optional) Microsoft Expression Blend 2 December Preview. Recommended, but if you’re not into playing with the design stuff, you can skip this.

  5. (Optional) Farseer Physics Engine and Silverlight Samples.
    Recommended, because there are some really great Silverlight samples by Bill Reiss in the download.

Creating the Physics Simulator

 

The PhysicsSimulator class is your main communication channel with the Physics Engine. If we examine Page.xml.cs, we can see the create call, which passes in a value for gravity. In this case, gravity will be straight down in the vertical (y) direction with a value of 500:

 

PhysicsSimulator _physicsSimulator;

_physicsSimulator = new PhysicsSimulator(new Vector2(0, 500));

_physicsSimulator.Iterations = 10;

 

We also optionally set Iterations which will affect the precision of the physics calculations, at the cost of performance.

 

Creating the “Sprites”

 

User Controls are a convenient mechanism for creating and animating the characters (or Sprites) in your game. You can draw them out in Expression Blend, and even include Storyboard animations to bring them to life.

 

We need to be sure to add a RotateTransform and TranslateTransform to the User Controls. These will be required for integration with Farseer, since the physics engine will determine position and rotation of the sprites at all times.

 

In the demo application, there are three User Controls defined:

 

  1. ucHead.xaml – this is the cute little head that drops from the sky and slams into the ground. Note that there are two Storyboard animations defined for the head: timeLineMoveEyes, which gives the little bugger some life by moving his eyes around, and timeLineOuchy, which plays when the head collides with another sprite.

  2. ucGround.xaml – the grassy floor that the heads collide with initially.

  3. ucWall.xaml – this is used for both the left and right side “walls” which keep the little heads from bouncing off our playing field.

 

If we look at each the XAML for any of these user controls, we can see that there are two transforms defined for the main canvas:

 

<Canvas.RenderTransform>

    <TransformGroup>

      <!-- This transform conrols the rotation-->

      <RotateTransform x:Name="rotateSprite" Angle="0" CenterX="30" CenterY="30"/>

      <TranslateTransform x:Name="translateTransform" X="0" Y="0"/>

    </TransformGroup>

  </Canvas.RenderTransform>

 

… these transforms will be used to keep the Farseer Physics Bodies in sync with our user controls’ positions. One thing to note which can be confusing is that the Farseer Engine keeps track of x,y position at the center of an object, instead of at the top left which we are used to. So the TranslateTransform will be used to keep that centered position of the object at our top, left position on screen.

 

Also note that each of these user controls inherits from SpriteBase instead of Control:

 

namespace HeadDrop

{

    public class ucHead : SpriteBase

    {

 

This technique was explained in an earlier blog post, any allows for some OOP and code reuse. SpriteBase contains basic sprite information such as the Farseer Body Object, position, and state.

 

We also need to define the Physics Body and Geometry (for collisions) for each sprite. Let’s examine the code in ucHead.xaml.cs.

 

First,we define the Physics body, which gives the object a location and size in the simulated world. In the case of the “head sprites” we want to create a circular body to match their shape. We pass in an instance of the Physics Simulator, the radius of the circle, and a mass value:

 

BodyObject = BodyFactory.Instance.CreateCircleBody(physicsSim, (float)getWidth / 2, 0.5f);

 

Next, we define the Geometry of the sprite, which is used for collision detection by the Physics Engine. We call CreateCircleGeometry passing in the Physics Simulator, the BodyObject defined in the call above, the radius of the circle, and also a parameter called collisionGridCellSize – which is used to change the accuracy of collision detection at the cost of performance. Depending on your game or simulation, you may want to play with the value of collisionGridCellSize if you are seeing jittery movement or other collision issues.

 

fsc.Geometry headGeometry = fsc.GeometryFactory.Instance.CreateCircleGeometry(physicsSim, BodyObject, (float)getWidth / 2, 20);

 

Next, we set up the Collision event handler, which will fire when this sprite collides with other sprites in another CollisionGroup. We should also give the geometry a unique Tag value, as this is a handy way to identify it when collision events occur:

 

headGeometry.Tag = "headGood";

headGeometry.CollisionHandler += new FarseerGames.FarseerPhysics.Collisions.Geometry.CollisionHandlerDelegate(HandleCollision);

 

 

The Timer Event

 

Inside our Game Timer Event (_timer_Completed, implemented as a Storyboard), we need to be sure to update the Physics Simulator to a new point in time, so that it can calculate the new positions and velocities of all objects in the simulation. To do so, we simply call Update on the Physics object, passing in a time span that we wish to update to:

 

_physicsSimulator.Update(.02f);

 

Once this call is made, the Body objects in the Farseer library will have the new positions calculated for all of our sprites (user controls). However, it is up to us to ensure that the sprites are actually moved to their new position in the UI. To ensure this, we call the Update method on all of our Sprites:

 

foreach (SpriteBase sprite in _spritesEnvironment)

{

    sprite.Update();

}

 

foreach (ucHead sprite in _spritesHeadGood)

{

    sprite.Update();

}

 

The implementation of this Update is contained in our SpriteBase class. This method synchronizes the X,Y position of the sprite to the X,Y position of the Farseer Body object:

 

public virtual void Update()

{

    if (BodyObject == null) return;

    if (_X != BodyObject.Position.X)

    {

        _X = BodyObject.Position.X;

        RootCanvas.SetValue<double>(Canvas.LeftProperty, _X);

    }

    if (_Y != BodyObject.Position.Y)

    {

        _Y = BodyObject.Position.Y;

        RootCanvas.SetValue<double>(Canvas.TopProperty, _Y);

    }

    if (BodyObject.Rotation != _rotation)

    {

        _rotation = BodyObject.Rotation;

        RotationTransform.Angle = (_rotation * 360) / (2 * Math.PI);

    }

}

 

Handling Collisions

 

If we look at ucHead.xaml.cs, we can see there is a HandleCollision event handler which we wired up above when creating the sprites:

 

private bool HandleCollision(fsc.Geometry g1, fsc.Geometry g2, fsc.ContactList contactList)

{

 

    if (BodyObject.LinearVelocity.X > 300 || BodyObject.LinearVelocity.Y > 300)

    {

        // this was a fairly hard hit - begin the ouchy animation

        _timeLineOuchy.Begin();

        Random rand = new Random();

    }

 

    // NOTE that we can track when two objects collide in the following way:

    // 1. add Tag values to each Geometry

    // 2. inside this event we compare tag values to see if a collision happened...

    if (g1.Tag.ToString() == "groundLeft" || g2.Tag.ToString() == "groundLeft")

    {

        // collision happened               

    }

 

    return true;

}

 

While this implementation of the Collision Handler is very simple, you can imagine that this would be a very handy method for triggering explosions and other events when two sprites collide.

 

In this example, we check if the LinearVelocity of the body is fairly high ( > 300) and if so, we play an “ouchy” animation which makes the little head frown because he has been hit L

 

Summary

 

I have only hit on the highlights of this sample, to help you understand how Silverlight and Farseer can work together. Hopefully the strategies I mentioned here will help you along in creating your own great physics games in Silverlight!

Permalink |  Trackback

Comments (13)   Add Comment
Re: Getting Started with Farseer Physics and Silverlight    By Anonymous on 12/22/2007 3:38 PM
Hi Andy,

This is Jeff Weber, I wrote Farseer. Nice to see this turorial should be helpful to a lot of people.

-Jeff

Re: Getting Started with Farseer Physics and Silverlight    By Anonymous on 12/23/2007 8:18 AM
Thanks Jeff - and thanks for all of the great work on Farseer!!

-Andy

Re: Getting Started with Farseer Physics and Silverlight    By Anonymous on 12/25/2007 12:19 PM
Thanks a lot Andy, this has helped me get started with the Farseer Physics Engine!

Re: Getting Started with Farseer Physics and Silverlight    By Anonymous on 1/24/2008 4:35 PM
Awesome... you've got me addicted to learning how to make games with Silverlight and Farseer!

Re: Getting Started with Farseer Physics and Silverlight    By Anonymous on 2/12/2008 5:43 PM
I've tried to get it going with what it seems is a later version of Farseer. My objects seem to be going at light speed for some reason zipping so fast they are barely visible on the screen. I'll have to check out some of the other tutorials, maybe the code is for outdated stuff.

Re: Getting Started with Farseer Physics and Silverlight    By Anonymous on 2/12/2008 6:21 PM
Nevermind, what was happening was that one of my objects was set to the same size as the Page.xaml file. This was screwing everything else up and making me scratch my head as I didn't see anything else wrong.

Getting started with Farseer Physics Engine 1.0.0.5 (Silverlight 2 beta 1)    By TrackBack on 4/1/2008 6:21 PM
Getting started with Farseer Physics Engine 1.0.0.5 (Silverlight 2 beta 1)
# Laumania.net

Getting started with Farseer Physics Engine 1.0.0.5 (Silverlight 2 beta 1)    By TrackBack on 4/1/2008 6:23 PM
Getting started with Farseer Physics Engine 1.0.0.5 (Silverlight 2 beta 1)
# Laumania.net

Getting started with Farseer Physics Engine 1.0.0.5 (Silverlight 2 beta 1)    By TrackBack on 4/2/2008 2:00 AM
Getting started with Farseer Physics Engine 1.0.0.5 (Silverlight 2 beta 1)
# Laumania.net

Getting started with Farseer Physics Engine 1.0.0.5 (Silverlight 2 beta 1)    By TrackBack on 4/3/2008 10:36 AM
Getting started with Farseer Physics Engine 1.0.0.5 (Silverlight 2 beta 1)
# Laumania.net

Getting started with Farseer Physics Engine 1.0.0.5 (Silverlight 2 beta 1)    By TrackBack on 4/17/2008 1:43 AM
Getting started with Farseer Physics Engine 1.0.0.5 (Silverlight 2 beta 1)
# Laumania.net

Getting started with Farseer Physics Engine 1.0.0.5 (Silverlight 2 beta 1)    By TrackBack on 7/5/2008 5:27 AM
Getting started with Farseer Physics Engine 1.0.0.5 (Silverlight 2 beta 1)
# Laumania.net

Getting started with Farseer Physics Engine 1.0.0.5 (Silverlight 2 beta 1)    By TrackBack on 8/16/2008 9:33 AM
Getting started with Farseer Physics Engine 1.0.0.5 (Silverlight 2 beta 1)
# Laumania.net


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