Here is a demo of a **TOP DOWN CAR** in Box2dweb. A big thanks to **iforce2d** for their help in steering wheel. Their tutorials were of great help.

The main problem in making this car is cancelling the perpendicular velocity of each wheel else the car will just start rotating as soon as we change the direction by rotating the wheel. As of now there is no skidding in the car i.e. the car moves as if it sticks to the ground. This is implement by adding a velocity with magnitude equal to perpendicular velocity of wheel but in opposite direction to each wheel. So if we want the car to skid, say when the fast moving car suddenly turns, we will add perpendicular velocity slightly less than actual.

**STEP 1**: Create a world with zero gravity. Since we are creating a top down view, we don't need gravity.

var world = new b2World(new b2Vec2(0,0), true);

**STEP 2**: Create the body of car and four wheels. One thing to notice is that wheels have been set as

*. The reason for this is that I didn't want the wheel to collide with other objects in the world. We can safely set the*

**sensor****property to false.**

*sensor*var bodyDef = new b2BodyDef; bodyDef.type = b2Body.b2_dynamicBody; bodyDef.position.Set(10,8); var fixDef = new b2FixtureDef; fixDef.density = 30; fixDef.friction = .8; fixDef.restitution = 0.1; fixDef.shape = new b2PolygonShape; fixDef.shape.SetAsBox(.5,1.5); //CAR BODY var car = world.CreateBody(bodyDef); car.CreateFixture(fixDef); //WHEELS var xx = car.GetWorldCenter().x; var yy = car.GetWorldCenter().y; var fr = wheel(xx+.5,yy-1); //front right wheel var fl = wheel(xx-.5,yy-1); //front left wheel var rr = wheel(xx+.5,yy+1); //rear right wheel var rl = wheel(xx-.5,yy+1); //rear left wheel function wheel(x,y) { var bodyDef = new b2BodyDef; bodyDef.type = b2Body.b2_dynamicBody; bodyDef.position.Set(x,y); var fixDef = new b2FixtureDef; fixDef.density = 30; fixDef.friction = 10; fixDef.restitution = 0.1; fixDef.shape = new b2PolygonShape; fixDef.shape.SetAsBox(.2,.4); fixDef.isSensor = true; var wheel = world.CreateBody(bodyDef); wheel.CreateFixture(fixDef); return wheel; }

**STEP 3**: Join the wheels to car body using

**revolute joints**. One thing to notice is to enable motor in the revolute joint but set it's speed to zero. If the motor is not enabled, we won't be able to steer the wheel.

var jfr = revJoint(car,fr); // Joint between car body and front right wheel var jfl = revJoint(car,fl); // Joint between car body and front left wheel var jrr = revJoint(car,rr); // Joint between car body and rear right wheel var jrl = revJoint(car,rl); // Joint between car body and rear left wheel // Revolute Joints function revJoint(body1,wheel) { var revoluteJointDef = new b2RevoluteJointDef(); revoluteJointDef.Initialize(body1, wheel, wheel.GetWorldCenter()); revoluteJointDef.motorSpeed = 0; revoluteJointDef.maxMotorTorque = 1000; revoluteJointDef.enableMotor = true; revoluteJoint = world.CreateJoint(revoluteJointDef); return revoluteJoint; }

**STEP 4**: Receiving input from keyboard and STEERING. I'm using jQuery.

var maxSteeringAngle = 1; var steeringAngle = 0; var STEER_SPEED = 3; var mspeed; var sf,sb = false; var ENGINE_SPEED = 300; $(window).keydown(function(e) { var code = e.keyCode; console.log(code); if(code == 65) //LEFT steeringAngle = -maxSteeringAngle; if(code == 68) //RIGHT steeringAngle = maxSteeringAngle; if(code == 83) //FORWARD sf = true; if(code == 87) //BACKWARD sb = true; }); $(window).keyup(function(e) { var code2 = e.keyCode; if(code2 == 68) steeringAngle = 0; if(code2 == 65) steeringAngle = 0; if(code2 == 87) sb = false; if(code2 == 83) sf = false; });More about the variable

**steeringAngle**to be discussed in next step.

Here

**maxSteeringAngle**is the maximum angle wheel can turn. Right now it is

**One Radian**.

**STEER_SPEED**decides the speed of rotation of wheel. It is arbitrarily chosen as 3. Higher the value more will be rotation speed.

Significance of

**steeringAngle**will be discussed shorlty.

Now put the following code in the

**update()**.

mspeed = steeringAngle - jfl.GetJointAngle(); jfl.SetMotorSpeed(mspeed * STEER_SPEED); mspeed = steeringAngle - jfr.GetJointAngle(); jfr.SetMotorSpeed(mspeed * STEER_SPEED);What happens here is if we want to turn right, we press 'd' (code = 68). The value of

*is set to*

**steeringAngle***i.e. 1 radian.*

**maxSteeringAngle**Now in update function a variable

**mspeed**is set to the difference between

**steeringAngle**and current wheel angle. Since we are steering it

**right**, 'current wheel angle' will be positive. Now we set the joint motor speed equal to product of this

*mspeed*variable and

*STEER_SPEED*and the wheel rotates to right.

As long as 'd' key is pressed

**steeringAngle**is 1 radian and

*joint*.GetJointAngle() goes on increasing which decreases the difference and hence the

*mspeed*variable. This goes on until the wheel has rotated by 1 radian and at this point the value of

*mspeed*variable is zero. At this point there will no further rotation of the wheel even if the key 'd' is pressed.

Now at this point when the we release the 'd' key the value of

**steeringAngle**is set to zero and the value of

**mspeed**will be negative as the joint has positive value of 1 radian. Since the value of

**mspeed**is negative, wheel will start rotating in other direction until the joint angle becomes zero again.

The same will happen when we want to steer left by pressing 'a' button.

**STEP 5**: Moving forward and cancelling lateral velocity.

Add these codes in your file.

var p1r = new b2Vec2(); var p2r = new b2Vec2(); var p3r = new b2Vec2(); var p1l = new b2Vec2(); var p2l = new b2Vec2(); var p3l = new b2Vec2(); function steerforward() { fr.ApplyForce(new b2Vec2(p3r.x,p3r.y),fr.GetWorldPoint(new b2Vec2(0,0))); fl.ApplyForce(new b2Vec2(p3l.x,p3l.y),fl.GetWorldPoint(new b2Vec2(0,0))); } function steerbackward() { fr.ApplyForce(new b2Vec2(-p3r.x,-p3r.y),fr.GetWorldPoint(new b2Vec2(0,0))); fl.ApplyForce(new b2Vec2(-p3l.x,-p3l.y),fl.GetWorldPoint(new b2Vec2(0,0))); } function cancelVel(wheel) { var aaaa=new b2Vec2(); var bbbb=new b2Vec2(); var newlocal=new b2Vec2(); var newworld=new b2Vec2(); aaaa=wheel.GetLinearVelocityFromLocalPoint(new b2Vec2(0,0)); bbbb=wheel.GetLocalVector(aaaa); newlocal.x = -bbbb.x; newlocal.y = bbbb.y; newworld = wheel.GetWorldVector(newlocal); wheel.SetLinearVelocity(newworld); }And following codes in

**update()**.

cancelVel(fr); cancelVel(fl); cancelVel(rr); cancelVel(rl); p1r = fr.GetWorldCenter(); p2r = fr.GetWorldPoint(new b2Vec2(0,1)); p3r.x = (p2r.x - p1r.x)*ENGINE_SPEED; p3r.y = (p2r.y - p1r.y)*ENGINE_SPEED; p1l = fl.GetWorldCenter(); p2l = fl.GetWorldPoint(new b2Vec2(0,1)); p3l.x = (p2l.x - p1l.x)*ENGINE_SPEED; p3l.y = (p2l.y - p1l.y)*ENGINE_SPEED; if(sf == true) steerforward(); if(sb == true) steerbackward();First let's see cancelVel(). In this function we are passing the wheel bodies to cancel the perpendicular velocity on the wheel. In this cancelVel() we see four vectors --

**aaaa**,

**bbbb**,

**newlocal**and

**newworld**.

1)

**aaaa**is the vector which stores the velocity of the concerned wheel at its center position (0,0). This velocity vector may have a component perpendicular to wheel.

2)

**bbbb**vector converts vector

**aaaa**in local coordinates (UV coordinates).

3)

**newlocal**vector stores the vector

**bbbb**with the U direction flipped i.e. local velocity in perpendicular (U) direction is made negative. This step effectively cancels the perpendicular component of velocity.

4) This

**newlocal**vector is converted to world coordinates (XY) using

**GetWorldVector()**and is stored in

**newworld**vector.

5) This velocity vector when applied to wheel does not cause any rotation of car. The perpendicular component of

**newlocal**vector deletes the velocity in the other perpendicular direction of the wheel.

**SUPERIMPOSITION**.

The following images may help in better understanding.

Now to steer forward we press the '

**w**' button which sets the variable '

**sf**' to true. Now if you look in update() if

**sf**is true steerforward() is called. And this steerforward() applies a force on both the front wheels which makes the car move. If

**sf**is false, no force will be applied.

Same goes for steering backward where

**sb**variable takes over.

Now you must be wondering what

**p1r**,

**p2r**and

**p3r**vectors are (

**r**stands for right and

**l**stands for left). Let me explain. We all know vectors are product of magnitude and direction where direction is itself a unit vector (magnitude = 1). So here we must define a unit vector first.

1)

**vector p1r**stores the world coordinates of center of wheel (local point 0,0).

2)

**vector p2r**stores the world coordinates of a point on wheel 1 unit back along the length of the wheel (local point 0,1).

3) So to get '

**x**' value for Engine Speed we subtract the '

**x**' value of

**p2r**and

**p1r**(unit vector) and multiply it my

**engine speed**(magnitude).

4) Same is done to get '

**y**' value.

5) In steerforward(), this vector

**p3**is applied to both wheels and in steerbackward(), vector

**p3**is applied in negative direction.

This way we apply a force in the direction of wheel.

That's it! We're done here. If you have any problem in understanding, please leave a

*comment*or

*reply*.

Click on the canvas and then use w - forward, s - backward, a - left and d - right to move the car.