Single axis lineardamping (or another way to do car tires)

Jun 26, 2011 at 2:01 PM

Hi, is there a way to apply linear damping or - because this is a top-down game - friction in only 1 axis? I'm trying to get a very simple top-down car simulation going on, and my idea to prevent sideways movement is to have 'tires' that have only friction on the normal axis of the car's direction. I looked at the FrictionJoint, but that also takes a float as force unfortunately.

Anybody an idea?

Jun 26, 2011 at 6:27 PM

you can get the speed facting the cars angle (and also normal to it) using the Vectro2.Dot function.

a very very old code to split up vectors

public static void VectorSplit(Vector2D vec, double angle, out Vector2D Front, out Vector2D Side)
                Vector2D vecfacting = new Vector2D(angle);
                Vector2D vecside = new Vector2D(vecfacting.Y, -vecfacting.X);
                double lfront =vec.Dot(vecfacting);
                double lside = vec.Dot(vecside);
                Front = vecfacting;
                Side = vecside;
Jun 27, 2011 at 9:19 AM

Thanks, HellGate. 
You suggest I manually adjust the velocity to simulate friction?

I was hoping for a way to adjust the LinearDamping or the FrictionJoint to work with a Vector2. 

Jul 7, 2011 at 4:32 AM

Hi HellGate and Jordos!

Interestingly I am facing a very similar challenge right now. I have a character that navigates up and down the screen while also moving sideways. Now I want to apply some LinearDamping on the Y axis only. When I set the LinearDamping it slows down both axis. I don't mind adjusting the velocity on the fly to compensate and adjust to the LinearDamping, although how what go about to retrieve the force I need to apply on the X axis to compensate the LinearDamping that was applied?

Naively I even already tried to update the following line in Farseer itself. :) I changed

b.LinearVelocityInternal *=

MathUtils.Clamp(1.0f - step.dt * b.LinearDamping, 0.0f, 1.0f);

 to the following lines:


b.LinearVelocityInternal.X *= MathUtils.Clamp(1.0f - step.dt, 0.0f, 1.0f);
b.LinearVelocityInternal.Y *= MathUtils.Clamp(1.0f - step.dt * b.LinearDamping, 0.0f, 1.0f);

but that didn't have the desired effect.

Any information on how to deal with this is much appreciated,


Jul 7, 2011 at 8:18 AM

CaptainTom, I found a piece of code on the Box2D forum that was very useful. I have it fixed now and got my cars driving pretty nicely :)
Will post the code when I get home! 

Jul 7, 2011 at 10:52 AM

yea there is a tut for Box2D somewhere that shows a topdown and a sidescroller car but i can't find the link anymore

Jul 7, 2011 at 12:01 PM
Edited Jul 7, 2011 at 12:02 PM

Here it is:

But this one's better (TensorDamping controller):

Jul 8, 2011 at 10:45 AM

This is my code for a wheel. Thanks to the writers of the examples I linked above. The only interesting part happens in the update method, where the friction is applied.

My cars are bumper cars with 3 wheels, of which one has motorpower and steering. It works really good!
The steering might be unusual, but for me this is exactly how I needed it (when the player pushes the controller stick to the right, I want the car to drive to the right, whatever orientation).

    public class Wheel
        public Body WheelBody { get; private set; }
        public float sidewaysFriction;
        private World world;
        private RevoluteJoint joint;
        private Body chassis;        
        private Mat22 frictionMatrix;
        private float steerRotation;

        public Wheel(World world, Body chassis, Vector2 localPosition, float sidewaysFriction, float wheelWidth, float wheelLength)
   = world;
            this.chassis = chassis;
            this.sidewaysFriction = sidewaysFriction;
            this.frictionMatrix = new Mat22(-sidewaysFriction, 0, 0, 0);

            this.WheelBody = BodyFactory.CreateBody(world);
            this.WheelBody.BodyType = BodyType.Dynamic;
            this.WheelBody.Position = chassis.Position + localPosition;
            this.WheelBody.Rotation = chassis.Rotation;
            this.WheelBody.UserData = this;
            this.WheelBody.SleepingAllowed = false;
            this.WheelBody.LinearDamping = 0;

            Fixture fixture = FixtureFactory.AttachRectangle(wheelWidth, wheelLength, 1, Vector2.Zero, WheelBody);
            fixture.IsSensor = true;
            fixture.Friction = 0;
            fixture.Restitution = 0;

            joint = new RevoluteJoint(chassis, WheelBody, localPosition, Vector2.Zero);
            joint.LowerLimit = joint.UpperLimit = 0;
            joint.MotorEnabled = true;
            joint.MaxMotorTorque = 100;

            steerRotation = 0;

        public void Destroy()

        /// <summary>
        /// Change the steerrotation (direction) of the wheel.
        /// </summary>
        /// <param name="steerRotation">The rotation in radians with 0 being to the right, CCW.</param>
        public void SetSteerRotation(float steerRotation)
            this.steerRotation = (steerRotation - 0.5f * (float)Math.PI) - chassis.Rotation;

        // This will apply wheel friction and motorforce
        public void Update(float motorForce = 0)
            // Steering
            this.WheelBody.Rotation = chassis.Rotation + steerRotation;
            // Friction
            Vector2 damping = WheelBody.GetWorldVector(MathUtils.Multiply(ref frictionMatrix, WheelBody.GetLocalVector(WheelBody.LinearVelocity)));
            WheelBody.LinearVelocity = WheelBody.LinearVelocity + damping;
            // Motorforce
            WheelBody.ApplyForce(Vector2.Transform(new Vector2(motorForce, 0),
                Matrix.CreateRotationZ(WheelBody.Rotation + 0.5f * (float)Math.PI)));   

Jul 8, 2011 at 11:52 AM

hmm looks nice but i just regioniced that FPE 3.2 doesn't have

FixtureFactory.AttachRectangle(wheelWidth, wheelLength, 1, Vector2.Zero, WheelBody);


Jul 9, 2011 at 3:31 AM

Thanks a lot for the two links! I was able to hack something together that works for my scenario so far! :)