Creating believable 2D platformer physics using a physics engine is always a challenge as character control is mostly “unrealistic” and often cannot be perfectly replicated using any simulator. I learned this the hard way when I embarked on project “Warpy”. However after receiving some help from another programmer, Robert Dodd of Boxycraft (http://boxycraft.wordpress.com), I managed to code a character movement system that I was happy with.

The whole idea stems from movable objects in a physics world having “wheels” to move around. Robert explains this technique in detail in his blog at: http://boxycraft.wordpress.com/2009/06/30/behind-boxboy/. Using some of the helpful advice he provided I managed to replicate his system using Farseer’s rectangle and circles body.

My rectangle body is connected to the circular wheel by the means of a RevoluteJoint (as illustrated in Robert’s Blog) with a motor enabled on it (travelling at a constant speed). The result is a character that is able to climb slopes, stop abruptly and collide into walls without travelling up them.

The next part of the character physics was to create the jump logic that would eventually control the player’s jumping and midair movement. This was done using a ray (like the image above) cast to the ground to determine player’s distance from the ground. When the player is closer than 5 pixels to the ground I set a flag so the player knows he is on the ground and is able to jump.

For midair movement, I studied Super Mario World for the snes and realized that when moving in midair Mario can adjust his position by moving left and right, however he could not move faster than his initial “lift off” velocity. Following this concept closely, I extracted the characters linear velocity along the x axis on initial lift off:

In jump function:

xJumpStrength = body.body.LinearVelocity.X;

In movement function:

if (jumpState != JumpState.GROUNDED)
{
// player is in mid air.. add force to body..
body.ApplyForce(new Vector2(xMovement * 10000, 0));

if (Math.Abs(body.LinearVelocity.X) > Math.Abs(xJumpStrength))
{
float jumpDir = body.body.LinearVelocity.X / Math.Abs(body.LinearVelocity.X);
body.LinearVelocity.X = jumpDir * Math.Abs(xJumpStrength);
}
}

The result of all this, is a character that sort of moves and behaves like Mario, but with support for odd angle slopes, round surfaces and polygon platforms!

p.s. if you’re wondering what Project “Warpy” is about, it’s a secret… at least for now. ๐