Making Pong using Farseer Physics engine

In my attempt to learn farseer physics engine(3.2), I decided to make a pong game, using the engine and XNA 4.0. Physics engine is an overkill for pong, but it sure helps to learn some of the basic concepts in a simple environment.

Please see my last post about some of the basic knowledge you need to get started.

This post is not about software design, and this is just my way of doing things.

Setting up the world:

I made a CollisionManager which contains the World from FPE, and exposes it as a property which others can use.

Creates a world with no gravity:

   1: mWorld = new World(Vector2.Zero);

In CollisionManager.Update(gameTime); ticks the world:

   1: mWorld.Step((float)gameTime.ElapsedGameTime.TotalMilliseconds * 0.001f);

By default, forces are automatically cleared in FPE, but in Box2D it is recommended to clear the forces.

   1: mWorld.ClearForces();

That is it! We’re done setting up the world.

Setting up the Ball:

GameOjbect just contains a reference to Body

   1: public class Ball : GameObject

Setting up the body:

   1: mBody = BodyFactory.CreateBody(CollisionManager.Instance.Worldphy, new Vector2(10, 0));

   2:  

   3: mBody.CreateFixture(new CircleShape(1.0f, 0.5f ));

   4:  

   5: mBody.FixtureList[0].Restitution = 1f;

   6:  

   7: mBody.BodyType = FarseerPhysics.Dynamics.BodyType.Dynamic;

   8:  

   9: mBody.ApplyLinearImpulse(new Vector2(50, 0));

  1. Create a body in world at vector2(10, 0)
  2. Creates a fixture out of a shape for mBody:
    1. A circle shape with a radius of 1.0f is created
    2. Density is 0.5f
  3. For the fixture attached to body, we want to set the restitution. Restitution is a measure of bounciness of a collision (elasticity of collision). Value should be between 0 and 1.
    1. 0 = fully absorb the collision : dont bounce at all : inelastic collision
    2. 1 = perfect reflection : fully bounce back : elastic collision
  4. Setting the bodyType to be Dynamic
  5. Give the ball an initial ‘impulse’

Setting up a Paddle:

Paddle also inherits from GameObject:

   1: public class Paddle : GameObject

Setting up the body:

   1: Fixture fix = FixtureFactory.CreateRectangle(CollisionManager.Instance.Worldphy, 1, 3, 0.5f, posn);

   2: fix.Restitution = 0f;

   3: fix.Friction = 0f;

   4:  

   5: mBody = fix.Body;

   6: mBody.BodyType = BodyType.Dynamic;

This time we choose to create a body using fixtures.

  1. Create a fixture in world, with a body at position: ‘posn’ and rectangle shape of width 1 unit and height 3 units (units are in the MKS system) (I pass the posn as a vector2 in the constructor of Paddle)
  2. We want the restitution to be 0 since we dont want the paddle to bounce off. See above for what restitution is!
  3. Assign the body reference in fixture to body of parent GameObject
  4. Make the BodyType to be dynamic

Moving the paddle:

   1: if (Input.IsNewKeyPress(Keys.W))

   2: {

   3:     mBody.ApplyForce(new Vector2(0f, 10.0f));

   4: }

   5: else if (Input.IsNewKeyPress(Keys.S))

   6: {

   7:     mBody.ApplyForce(new Vector2(0f, -10.0f));

   8: }

When W is pressed, we want the paddle to move up (we apply a force in up direction with magnitude of 10f). When S is pressed, we want the paddle to move down (we apply a force in down direction with magnitude of -10f).

 

That’s it. Instantiate a paddle and a Ball and you’ll see a ball moving towards right and if you press W/S the paddle would move either up/down.

You’ll also notice the ball to fly off the screen because there is nothing to bound it. I used this code from one of the testSamples for farseer to generate a big box, which would prevent the ball or paddle to fly away.

   1: List<Vertices> borders = new List<Vertices>(4);

   2:  

   3: const float borderWidth = 0.2f;

   4: const float width = 40f;

   5: const float height = 25f;

   6:  

   7: //Bottom

   8: borders.Add(PolygonTools.CreateRectangle(width, borderWidth, new Vector2(0, height), 0));

   9:  

  10: //Left

  11: borders.Add(PolygonTools.CreateRectangle(borderWidth, height, new Vector2(-width, 0), 0));

  12:  

  13: //Top

  14: borders.Add(PolygonTools.CreateRectangle(width, borderWidth, new Vector2(0, -height), 0));

  15:  

  16: //Right

  17: borders.Add(PolygonTools.CreateRectangle(borderWidth, height, new Vector2(width, 0), 0));

  18:  

  19: List<Fixture> fixtures = FixtureFactory.CreateCompoundPolygon(mWorld, borders, 1, new Vector2(0, 0));

  20:  

  21: foreach (Fixture fixture in fixtures)

  22: {

  23:     fixture.Restitution = 1f;

  24:     fixture.Friction = 0;

  25: }

By default, the bodyType is static, which is what we’d want the outer box to be.

The code is very intuitive if you followed the above post and read the basics in my last post.


Box2D / Farseer Physics Engine basics

I recently wanted to use a physics engine for the game, and I saw a lot of documentation scattered across manual and the code. This is my effort to document as much as I can and hopefully it helps someone who are about to get started!

I am using Farseer Physics Engine 3.2 which is a port of Box2D (along with some other extra tools). Let’s get started:

Common Objects in the physics system:

– World
– (Rigid)Body
– Shape
– Fixture

World: World is the heart of FPE. It makes the whole Physics world tick. There are multiple parameters that can be tweaked in this for efficiency, performance, accuracy etc.

Rigid Body: Hard chunk of matter that keeps a track of the position of the object

Shape: Object’s Geometrical shape like circle, rectangle, polygon etc

Fixture: Fixture binds a shape to a body and adds material properties to the object. (Material properties such as density(mass per volume), friction, and restitution)

PS: Memory management in Box2D recommends never to "new" / "malloc" Body, Joint and Fixtures, since it has its own memory management implemented(Small Object Allocators). This does not apply to FPE.

World:
– Create world:

mWorld = new World(gravityVector); 

– Update World:

mWorld.Step((float)gameTime.ElapsedGameTime.TotalMilliseconds * 0.001f); -- 
ticks the world.

Basics can be read at: Simulating the world; sec 2.4 at http://www.box2d.org/manual.html#_Toc258082968

Read the rest of this entry »