Platformer Character Control (Farseer Physics Engine)

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.

Image courtesy of Robert Dodd

Image courtesy of Robert Dodd

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. :)

26 Responses to “Platformer Character Control (Farseer Physics Engine)”


  • Nice article, I like your idea of using the players initial jump velocity to control their speed in the air!

  • Wow thanks for commenting on my blog! :D I’ve just started it to share some of the stuff I’m working on with the community.

  • Great article! I’m a little stuck implementing it though. How are you making the circle you use as a wheel rotate? I tried applying a torque to it and directly accessing its Rotation property and neither worked. Any help or source code you could give me would be very much appreciated. Thanks in advance for your help :D

  • Sorry for the late reply… Been busy implementing some new features into the game I’m working on. If you’re using farseer, you can connect the wheel to the body using a RevoluteJoint. I used a patch written by Robert Dodd to get a motor on the joint so I could make it turn at a constant speed. You can get it at: http://farseerphysics.codeplex.com/SourceControl/PatchList.aspx.. second link at time of writing. Hope this helps :D

  • Would this work if your character were to just fall off an edge? I’m not trying to down the article (which is quite informative and a good way of implementing things. I myself looked at BoxyCraft’s implementation as well for my game) but it sounds like if you were to just fall off an edge, xJumpStrength would not be given a new value. Now I don’t know what you consider the “initial lift off” but I’m assuming it means when your Jump() method is called. One thing I think you could do is have a previousCanJumpState value and when previousCanJumpState = true and currentCanJumpState = false, then do xJumpStrength = LinearVelocity.X. Just a suggestion, it may not even be necessary for your game because it wouldn’t be that noticeable of an issue unless you have a huge cliff somewhere.

  • Yes I agree. I was rather hasty when writing this article. I have since changed my xJumpStrength to a fixed value rather then the speed the character jumped off at.. Thanks for pointing it out!

  • It would be nice if you could post the character’s code, not only the Jump function. It would realy help me (and others I believe).

    (Sorry for the double post)

  • Thanks for your interest! I may post example code when I have the time. (can’t post the code I have since I’m bound by the NDA of the project)

  • Hi Bryan, currently I’m doing a platform game and headache with the character part.

    I would like to ask how could you do the revolute joint and motor joint? what does that means?

    Is there any where I can look for some examples on creating revolute joint in farseer?

    I’ve looked through the simple samples of Farseer but I couldn’t see any example on revolute joint.

    Could you help me out about this?

  • Hi Cadrick! I’m not sure if the revolute joint is used in the samples but there is some information on it in the documentation.

    Here is a direct link to where it is used: http://www.farseergames.com/storage/farseerphysics/Manual2.1.htm#_Toc213068492. It’s an old manual but the code is pretty much the same. Although it doesn’t give exact code on how to implement it, the documentation explains what every parameter associated with creating/modifying a revolute joint means. The method to create a revolute joint is located in the JointFactory, which should be a singleton if memory serves me correctly.

    Secondly, the motor in the revolute joint is NOT part of the official farseer code. It’s a patch written by Robert Dodd (who also has an article on this on his blog, mentioned in this post). You can download the patch at: http://farseerphysics.codeplex.com/SourceControl/PatchList.aspx (Look for the patch by Robert). You will need to recompile farseer after applying the patch.

    Hope this helps!

  • Alright, I shall try it out first, thanks alot :D

  • Excellent article, however you’ve had me searching quite a while for that motor joint patch. It looks like you made a type so here’s the direct link to the motor joint patch:

    http://farseerphysics.codeplex.com/Project/Download/FileDownload.aspx?DownloadId=70619
    [quote=Robert Dodd]
    Added Motor to RevoluteJoint and FixedRevoluteJoint.

    to use: Motor_Enabled = true; Motor_Speed = 2.0f; Motor_MaxTorque = 10.0f;
    Easy :)
    [/quote]

    Oh and btw people: remember to use the JointFactory to create these joints and pass the PhysicsSimulator as first argument, that makes your life way easier :) .

  • Thanks for contributing! It isn’t very obvious where the patch section is in codeplex, it’s great that you listed it in your post.

  • Oh btw you don’t need the angle joint (just tested that) since:

    -The fixed angle joint will always keep the upper body pointing up (or forward)
    -The lower body (wheel) is fixed to the upper body, and since the upper body’s angle/rotation will never change, the lower body will always be at the bottom of the upper body the only degree of freedom it has is rotation.

    I think it might even break adding that angle joint :) .

  • The angle joint was a mechanism in Robert’s system that served as a brake for when the character was meant to stop abruptly. The joint would be attached/disattached to facilitate abrupt motion and halting. (The image was posted originally on Robert’s blog)

    I find that it may not be necessary to have the angle joint in farseer, as setting the motor_speed to 0 would produce a similar effect.

  • BTW, Im facing another problem now, since the character movement is actually a circle rolling and the circle in Farseer 2.x is actually not a perfect circle. How’d you guys overcome this problem? I’ve found out that while my character moving on the floor, I feel shakiness of the character due the circle.

  • Limiting the speed of the motor is a good place to start. Increasing/Decreasing the edges that make up the circle can affect the jerkiness as well. I’ve gave some thought to making a box at the feet of the character (with adjustable friction) to prevent the jerkiness but I never actually had to do it for my game as we managed to tweak the speed until we got something we liked.

  • Hmm, about the motor in revolute joint, actually how does it works?
    I have enable the motor and set some speed on it but it seems like not moving at all?
    So actually how should I make it move or stop?

  • 1 more problem, I follow the way boxycraft did for their character and I found out that when I jump and fall on the floor, the upper rectangle body will bounce awhile, so how could I totally cancel off the bouncing?

  • So I am trying to set up a character with the same concepts. and it works. sortof, but what I am wondering is how you got your character so responsive. ours has a pretty sluggish start when ever you start him moving. and he does not slow down/change directions very quickly ether. suggestions? this was a great post by the way.

  • Hi austin, I set the motor speed to a fixed value when I wanted to move the player, and back to 0 when the player was meant to stop. Because the wheel has high friction, and the speed affects the velocity not the acceleration, the character is able to stop and move abruptly.

  • Yay! I implemented it. Thanks for great tutorial.

  • Hi!,

    I have come across your article while trying to create a 2D character controller in Unity. And I wanted to ask you something. The Circle you are using for the down part of your controller won’t it cause that when player gets to the edge of a platform it will start going down a little (because the rounded part in sphere) until it falls?.

    Thanks in advance.

  • I cant find the patch for this, does anyone have a copy or a link of the file?

    Thanks

  • Excellent article, very enlightening on techniques for using the physics engine, thanks much! =)

  • I have the same problem Marting May has. Is there a best way to resolve it?

Leave a Reply