All science is either physics or stamp collecting


So let’s stop the stamp collecting we have been doing and get down to some real work.  The physics engine is the heart of your game.  Don’t understand physics?  Get a book and read.  Trust me this is important.  Even in the simplest game you need to know resistance, inertia, damping, velocity, etc…  Don’t try to build your own physics engine and don’t implement collisions without one.  I have made this mistake, as has pretty much every beginning game developer.  It seems simple at first:

“Okay so I have some objects, let me check for a collision.  Hmm when X2<=X1.  Cool it works, now lets add Y2<=Y1.  Sweet perfect collisions, wait which direction did I collide from, okay that’s left.  Now just three left to go.”

I have done it, and you won’t realize how much failure you have on your hands until its too late and death would be sweet release from the hell you have created.  You know why Lucifer was cast out of heaven?  Yep, built his own physics engine… and probably an encryption algorithm just for good measure.

So where to start?  Well Box2d is hot right now and if you are using XNA it is pretty easy to get set up using the Farseer port.  So where do I come in?  Well install it and open the samples.  Then try to get your own project working… did you just spend an hour trying to figure out what the hell screen manager is?  You and pretty much everyone else.  There are only a few things you need for the building blocks of any game, so let’s start simple.

For reference I am using Farseer 3.3.1 – Don’t worry about versions too much, the major changes are between 2 & 3, the point releases mean little, and the functions/factories are still similar.  Also in the interest of full disclosure, I am no expert at physics engines.  But I have struggled through other walkthroughs and thought I might be able to clear a few things up.

Just as in life the world is everything and nothing, deep I know.  Basically you have to create a world to do anything with a Physics engine but once that world is created you don’t go back to that object very often.

GameWorld = new World(Vector2.Zero);

Pretty easy, eh?  You just created a world, feel that rush of blood to your head?  Savor it and maybe get some help, because this is just a container and you haven’t done anything yet.  No day of rest for you!  So here I am creating a world with no gravity (top down game) but if you wanted gravity you could use – new World(new Vector2(0,10)).

The only thing you do with the world for now is call GameWorld.Step() in your main Update loop.  Step is the workhorse.  It iterates through all of your physics objects and calculates new forces and positions.  Don’t forget this and then get pissed that nothing is moving.

GameWorld.Step(Math.Min((float)gameTime.ElapsedGameTime.TotalSeconds, (1f / 30f)));

Now open one of your objects.  You will need to add a few vital pieces.  First a body.  Much like the real world bodies are a good thing when functioning properly.  Then we will add a shape under the body used for collisions.  And last a fixture which basically links your body to your shape.

public Body characterBody;
public CircleShape characterShape;
public Fixture characterFixture;

Body = new Body(Global.GameWorld);
Body.BodyType = BodyType.Dynamic;
Body.Mass = 2f;
Body.LinearDamping = 20f;
Body.Position = new Vector2(ConvertUnits.ToSimUnits(_X), ConvertUnits.ToSimUnits(_Y));
Body.CollisionCategories = Category.Cat1;
Fixture = Body.CreateFixture(new CircleShape(ConvertUnits.ToSimUnits(Width / 4), 1.0f));
Fixture.Restitution = 0f;
Fixture.OnCollision += MyOnCollision;

First create a body and pass in the GameWorld you created.  Next we set a Body type, in general your character, enemies and interactive elements will be dynamic.  Borders, walls and immovable obstacles will be static, you could also have backgrounds and tiles be static as long as they don’t have a collision category but that really is up to you since the physics engine won’t really be dealing with them.  It makes them unnecessary overhead, but it keeps all of your objects in the world.  The power is yours!

Next we set a few variables, mass and LinearDamping.  LinearDamping is basically a drag/resistive force.  It is useful for gracefully slowing a moving object down like they do in the real world.  No immediate stopping and no video game characters on ice (unless that is what you want).  These are two values that you will have to play with as there is no perfect answer for what to set these at.

This is followed by setting our initial position.  You will notice a function in here, ConvertUnits.ToSimUnits.  THIS IS SUPER IMPORTANT!  Farseer uses a different scale than what you use for drawing.  If you try to use the same scale, Farseer will slow to a crawl as it calculates numbers that approach the max values for the framework.  The demos they provide come with a simple ConvertUnits class.  Copy it right away and pass forces using ConvertUnits.ToSimUnits and pass positions back to be drawn using ConvertUnits.ToDisplayUnits.

This is where we get to some of the niceties of a framework for physics.  Collision categories.  You don’t need these initially but get use to them.  You don’t want a weapon from an enemy to strike their friend or you may want a spell or attack to pass through certain objects.  You can specify in your objects what their category is and what categories they collide with.  Very useful stuff.

Next create a fixture, this will be the collision circle for collision detection.  You don’t need to do anything else, that is it.  You can use any shape.  For more complex models you may want a polygon.

Then set the collision function, basically you are subscribing to notifications of when collisions occur.  You can then react to them (do logic and return true) or ignore them (do logic and return false).  This is a whole topic in and off itself so I will save it to next time, but for now set up a receiver in a custom event like the event below:

public bool MyOnCollision(Fixture f1, Fixture f2, Contact contact)
{
    return true;
}

The last thing to talk about is Body.UserData.  This is a very useful object which allows you to create a custom object and have it tag along for the ride.  There are times where you need to know more information then is present in the collision data to determine how to react (i.e. what type of attack just occured).

From there setting up a basic draw object with a draw function is easy:

SpriteBatch.Draw(Texture, new Rectangle(DestRect.X – Global.ViewAreas[viewportIndex].X, DestRect.Y- Global.ViewAreas[viewportIndex].Y, DestRect.Width, DestRect.Height), SourceRect, DrawColor, Rotation, Origin, Effects, LayerDepth);

In the above DestRect.X and Y are the position of the body, so Object.Body.Position.X, but don’t forget to convert to display units first.

I will go into the collision event and other types of joints such as weld joints in a later installment, but this should at least get your characters reacting to collisions.  I will also talk about another important constructor argument to the World object which will allow us to place boundaries in the game.  I will post a video once I am done with these other sections.

Feel free to let me know if you have any points of clarification or additional information.

  1. No trackbacks yet.

Leave a comment