This project has moved and is read-only. For the latest updates, please go here.

Trouble getting started with Farseer in XNA

Jul 22, 2009 at 6:05 PM

I'm having problems with the way Farseer is behaving trying to bounce one non-static rectangle against another static one. The moving rectangle penetrates the floor in an irregular manner before stopping in a position which fully penetrates the floor - not what I was looking for.

The static rectangle is the "floor", and the moving rectangle is called "rectangle".  In the default XNA Game1 class I declare a variable for the physics engine, and a texture, body, and geom for each rectangular sprite:

PhysicsSimulator physicsSimulator;

Texture2D floorTexture;
Body floorBody;
Geom floorGeom;

Texture2D rectangleTexture;
Body rectangleBody;
Geom rectangleGeom;
In the Initialize method, the physics engine is instantiated, and the floor and rectangle have their associated textures, bodies, and geoms loaded or created:
(the position of the bodies, and the width and height of the bodies and geoms are determined by the width and height of the textures for each associated object.
The objects will be drawn with their origins assumed to be the center of the rectangular textures. The physics engine is started with some gravity.
floorTexture = Content.Load("floor");
rectangleTexture = Content.Load("rectangle");

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

floorBody = BodyFactory.Instance.CreateRectangleBody(physicsSimulator, floorTexture.Width, floorTexture.Height, 1.0f);
floorGeom = GeomFactory.Instance.CreateRectangleGeom(physicsSimulator, floorBody, floorTexture.Width, floorTexture.Height);
floorBody.IsStatic = true;
floorGeom.RestitutionCoefficient = 0.8f;
floorBody.Position = new Vector2(floorTexture.Width / 2, graphics.GraphicsDevice.Viewport.Height - (floorTexture.Height / 2));

rectangleBody = BodyFactory.Instance.CreateRectangleBody(physicsSimulator, rectangleTexture.Width, rectangleTexture.Height, 1.0f);
rectangleGeom = GeomFactory.Instance.CreateRectangleGeom(physicsSimulator, rectangleBody, rectangleTexture.Width, rectangleTexture.Height);
rectangleBody.IsStatic = false;
rectangleGeom.RestitutionCoefficient = 0.85f;
rectangleBody.Position = new Vector2(rectangleTexture.Width / 2, rectangleTexture.Height / 2);
rectangleBody.Position = Vector2.Add(rectangleBody.Position, new Vector2(graphics.GraphicsDevice.Viewport.Width / 2, 0));
In the Update method, the physics engine is also updated:
physicsSimulator.Update(gameTime.ElapsedGameTime.Milliseconds * .001f);
The Draw method just draws the sprites with their texture coordinate origins set to the center of the textures, to match up with the body location:

spriteBatch.Draw(floorTexture,	// texture
	floorBody.Position,	// position
	null,		// source rectangle
	Color.White,	// color
	0f,		// rotation
	new Vector2(floorTexture.Width / 2, floorTexture.Height / 2),	// origin
	new Vector2(1,1),	// scale
	SpriteEffects.None,	// sprite effects
	0f);		// layer depth

spriteBatch.Draw(rectangleTexture,	// texture
	rectangleBody.Position,  	// position
	null,			// source rectangle
	Color.White,		// color
	0f,			// rotation
	new Vector2(rectangleTexture.Width / 2, rectangleTexture.Height / 2),	// origin
	new Vector2(1, 1),		// scale
	SpriteEffects.None,		// sprite effects
	0f);			// layer depth



I thought using Farseer would be as simple as creating bodies and geoms using the Factory methods in the physics engine, and then just letting the engine update their positions. 
If I modify the Simple Samples project that comes with Farseer, objects tend to bounce in a stable manner, but they don't have pixel-perfect contact unless you're seeing the extra borders in debug view.
What am I missing here? Is there a lot more checking I need to be doing in code to ensure the objects correctly bounce again one another?
Jul 22, 2009 at 7:43 PM

It is indeed as simple as creating a body and a geom.

It would be great if you are able to upload your game to a free upload site or contact me by clicking on my username. I will take a quick look at your project and determine where the problem lies. The problem might be in the size of your textures and that is not visible in the text you wrote.

Jul 24, 2009 at 4:01 PM

Ok genbox, you can download the Visual Studio 2008 solution from here:

Here's a short YouTube video what happens when the program runs:

Jul 24, 2009 at 7:51 PM

You forgot to draw the rotation of the geometry (rectangleGeom). And your restitution coefficient is really high, so high that your current settings will make the geometry bounce endlessly (jittering) because of position error. Try giving it a lower restitution coefficient to eliminate that.

Jul 24, 2009 at 8:44 PM

Yep, not setting the rotation of the sprite texture to the value of the geom rotation pretty much fixed it.

Thanks, genbox.