Hello
http://projects.omikrosys.com/gaming/racing/moving.htmlIf you move the car using arrow keys , the wheels would go out of track and start hanging out of the main car body.
The wheel should stick to its position on the wheel.
What is wrong with the code :
Code:
var b2Vec2 = Box2D.Common.Math.b2Vec2
, b2AABB = Box2D.Collision.b2AABB
, b2BodyDef = Box2D.Dynamics.b2BodyDef
, b2Body = Box2D.Dynamics.b2Body
, b2FixtureDef = Box2D.Dynamics.b2FixtureDef
, b2Fixture = Box2D.Dynamics.b2Fixture
, b2World = Box2D.Dynamics.b2World
, b2MassData = Box2D.Collision.Shapes.b2MassData
, b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape
, b2CircleShape = Box2D.Collision.Shapes.b2CircleShape
, b2DebugDraw = Box2D.Dynamics.b2DebugDraw
, b2MouseJointDef = Box2D.Dynamics.Joints.b2MouseJointDef
, b2Shape = Box2D.Collision.Shapes.b2Shape
, b2RevoluteJointDef = Box2D.Dynamics.Joints.b2RevoluteJointDef
, b2Joint = Box2D.Dynamics.Joints.b2Joint
, b2PrismaticJointDef = Box2D.Dynamics.Joints.b2PrismaticJointDef
;
var game = {
'key_down' : function(e)
{
var code = (e.keyCode);
var v = 100;
//left
if(code == 37)
{
steering_angle = -1 * max_steer_angle;
}
//up
if(code == 38)
{
engine_speed = -1*top_speed;
}
//right
if(code == 39)
{
steering_angle = max_steer_angle;
}
//down
if(code == 40)
{
engine_speed = top_speed;
}
} ,
'key_up' : function(e)
{
engine_speed = 0;
steering_angle = 0;
} ,
};
var engine_speed = 0;
var steering_angle = 0;
var steer_speed = 1.5;
var max_steer_angle = Math.PI/3;
var top_speed = 5000;
var world;
var ctx;
var canvasWidth;
var canvasHeight;
var canvasTop;
var canvasLeft;
var car;
/*
Draw a world
this method is called in a loop to redraw the world
*/
function drawWorld(world, context)
{
for (var j = world.GetJointList() ; j ; j = j.GetNext())
{
drawJoint(j, context);
}
for( var b = world.GetBodyList() ; b ; b = b.GetNext())
{
for( var f = b.GetFixtureList() ; f != null ; f = f.GetNext())
{
var shape = f.GetShape();
var shapeType = shape.GetType();
if(isNaN(b.GetPosition().x))
{
alert('Invalid Position : ' + b.GetPosition().x);
}
else
{
drawShape(b , shape , context);
}
}
}
ctx.font = 'bold 18px arial';
ctx.textAlign = 'center';
ctx.fillStyle = '#000000';
ctx.fillText("Use arrow keys to move the car", 400, 20);
//ctx.font = 'bold 14px arial';
//ctx.fillText("Performance will vary by browser", 400, 40);
}
function drawJoint(joint, context)
{
var b1 = joint.GetBodyA();
var b2 = joint.GetBodyB();
var x1 = b1.GetPosition();
var x2 = b2.GetPosition();
var p1 = joint.GetAnchorA();
var p2 = joint.GetAnchorB();
context.strokeStyle = '#00eeee';
context.beginPath();
switch (joint.m_type)
{
case b2Joint.e_distanceJoint:
context.moveTo(p1.x, p1.y);
context.lineTo(p2.x, p2.y);
break;
case b2Joint.e_pulleyJoint:
// TODO
break;
default:
if (b1 == world.m_groundBody)
{
context.moveTo(p1.x, p1.y);
context.lineTo(x2.x, x2.y);
}
else if (b2 == world.m_groundBody)
{
context.moveTo(p1.x, p1.y);
context.lineTo(x1.x, x1.y);
}
else
{
context.moveTo(x1.x, x1.y);
context.lineTo(p1.x, p1.y);
context.lineTo(x2.x, x2.y);
context.lineTo(p2.x, p2.y);
}
break;
}
context.stroke();
}
function drawShape(body , shape, context)
{
context.strokeStyle = '#000';
if (shape.density == 1.0)
{
context.fillStyle = "red";
}
else
{
context.fillStyle = "#fff";
}
context.beginPath();
switch (shape.GetType())
{
case b2Shape.e_polygonShape:
{
var poly = shape;
var vert = shape.GetVertices();
var position = body.GetPosition();
//b2Math.MulMV(b.m_xf.R , vert[0]);
var tV = position.Copy();
var a = vert[0].Copy();
a.MulM( body.GetTransform().R );
tV.Add(a);
//var tV = b2Math.AddVV( position , b2Math.MulMV(b.m_xf.R, vert[0]) );
context.moveTo(tV.x, tV.y);
for (var i = 0; i < vert.length; i++)
{
var v = vert[i].Copy();
//v.MulM( body.m_xf.R );
v.MulM( body.GetTransform().R );
v.Add(position);
//var v = b2Math.AddVV(position, b2Math.MulMV(b.m_xf.R, vert[i]));
context.lineTo(v.x, v.y);
}
context.lineTo(tV.x, tV.y);
/*
//m_position is a (x, y) vector having positions of the body
var tV = b2Math.AddVV( poly.m_position , b2Math.b2MulMV(poly.m_R , poly.m_vertices[0]) );
context.moveTo(tV.x, tV.y);
//for square things there are 4 vertices :)
//for sqyare things m_r is 1 , 0 | 0 , 1 matrix ?? what does it means ? unit matrix of order 2 ?
for (var i = 0; i < poly.m_vertexCount; i++)
{
var v = b2Math.AddVV(poly.m_position, b2Math.b2MulMV(poly.m_R, poly.m_vertices[i]));
context.lineTo(v.x, v.y);
}
context.lineTo(tV.x, tV.y);*/
}
break;
}
//this will fill a shape
//context.fill();
//this will create the outline of a shape
context.stroke();
}
/*
Create box2d world object
*/
function createWorld()
{
var gravity = new b2Vec2(0, 0);
var doSleep = true;
world = new b2World(gravity , doSleep);
return world;
}
/*
Create standard boxes of given height , width at x,y
*/
function createBox(world, x, y, width, height, options)
{
//default setting
options = $.extend(true, {
'density' : 1.0 ,
'friction' : 1.0 ,
'restitution' : 0.2 ,
'linearDamping' : 0.0 ,
'angularDamping' : 0.0 ,
'gravityScale' : 1.0 ,
'type' : b2Body.b2_dynamicBody
}, options);
var body_def = new b2BodyDef();
var fix_def = new b2FixtureDef;
fix_def.density = options.density;
fix_def.friction = options.friction;
fix_def.restitution = options.restitution;
fix_def.shape = new b2PolygonShape();
fix_def.shape.SetAsBox( width , height );
body_def.position.Set(x , y);
body_def.linearDamping = options.linearDamping;
body_def.angularDamping = options.angularDamping;
body_def.type = options.type;
body_def.gravityScale = 0;
var b = world.CreateBody( body_def );
var f = b.CreateFixture(fix_def);
return b;
}
/*
This method will draw the world again and again
called by settimeout , self looped
*/
function step(cnt)
{
var stepping = false;
//fps = 60 , time steps
var fps = 60;
var timeStep = 1.0/fps;
var iteration = 1;
//move the world ahead , step ahead man!!
world.Step(timeStep, iteration);
update_car();
//first clear the canvas
ctx.clearRect( 0 , 0 , game.canvas_width, game.canvas_height );
//redraw the world
drawWorld(world , ctx);
//call this function again after 10 seconds
setTimeout('step(' + (cnt || 0) + ')', 10);
}
// main entry point
$(function()
{
//first create the world
world = createWorld();
game.ctx = ctx = $('#canvas').get(0).getContext('2d');
var canvas = $('#canvas');
game.canvas_width = canvasWidth = parseInt(canvas.width());
game.canvas_height = canvasHeight = parseInt(canvas.height());
//canvasTop = parseInt(canvasElm.style.top);
//canvasLeft = parseInt(canvasElm.style.left);
create_car();
$('body').keydown(function(e)
{
game.key_down(e);
});
$('body').keyup(function(e)
{
game.key_up(e);
});
step();
});
function create_car()
{
car_pos = new b2Vec2(300,300);
car_dim = new b2Vec2(20 ,35);
car = createBox(world , car_pos.x , car_pos.y , car_dim.x , car_dim.y , true , {});
var wheel_dim = new b2Vec2(4 , 8);
//front wheels
left_wheel = createBox(world , car_pos.x - car_dim.x , car_pos.y - car_dim.y / 2 , wheel_dim.x , wheel_dim.y , {});
right_wheel = createBox(world , car_pos.x + car_dim.x, car_pos.y - car_dim.y / 2 , wheel_dim.x , wheel_dim.y , {});
//rear wheels
left_rear_wheel = createBox(world , car_pos.x - car_dim.x , car_pos.y + car_dim.y / 2 , wheel_dim.x , wheel_dim.y , {});
right_rear_wheel = createBox(world , car_pos.x + car_dim.x, car_pos.y + car_dim.y / 2 , wheel_dim.x , wheel_dim.y , {});
var front_wheels = {'left_wheel' : left_wheel , 'right_wheel' : right_wheel};
for (var i in front_wheels)
{
var wheel = front_wheels[i];
var joint_def = new b2RevoluteJointDef();
joint_def.Initialize(car , wheel, wheel.GetWorldCenter());
//after enablemotor , setmotorspeed is used to make the joins rotate , remember!
joint_def.enableMotor = true;
joint_def.maxMotorTorque = 100000;
car[i + '_joint'] = world.CreateJoint(joint_def);
}
var rear_wheels = {'left_rear_wheel' : left_rear_wheel , 'right_rear_wheel' : right_rear_wheel};
for (var i in rear_wheels)
{
var wheel = rear_wheels[i];
var joint_def = new b2PrismaticJointDef();
joint_def.Initialize( car , wheel, wheel.GetWorldCenter(), new b2Vec2(1,0) );
joint_def.enableLimit = true;
joint_def.lowerTranslation = joint_def.upperTranslation = 0.0;
car[i + '_joint'] = world.CreateJoint(joint_def);
}
car.left_wheel = left_wheel;
car.right_wheel = right_wheel;
car.left_rear_wheel = left_rear_wheel;
car.right_rear_wheel = right_rear_wheel;
return car;
}
//This function applies a "friction" in a direction orthogonal to the body's axis.
function killOrthogonalVelocity(b)
{
var localPoint = new b2Vec2(0,0);
var velocity = b.GetLinearVelocityFromLocalPoint(localPoint);
var sidewaysAxis = b.GetTransform().R.col2.Copy();
//multiply vector with a constant;
sidewaysAxis.Multiply( velocity.x*sidewaysAxis.x + velocity.y*sidewaysAxis.y)
b.SetLinearVelocity(sidewaysAxis); //b.GetWorldPoint(localPoint));
}
function update_car()
{
killOrthogonalVelocity(car.left_wheel);
killOrthogonalVelocity(car.right_wheel);
killOrthogonalVelocity(car.left_rear_wheel);
killOrthogonalVelocity(car.right_rear_wheel);
var wheels = ['left' , 'right'];
//Driving
for(var i in wheels)
{
var d = wheels[i] + '_wheel';
var wheel = car[d];
var direction = wheel.GetTransform().R.col2.Copy();
direction.Multiply( engine_speed );
wheel.ApplyForce( direction , wheel.GetPosition() );
}
//Steering
for(var i in wheels)
{
var d = wheels[i] + '_wheel_joint';
var wheel_joint = car[d];
//set the motor speed
var mspeed;
//max speed - current speed , should be the motor speed , so when max speed reached , speed = 0;
mspeed = steering_angle - wheel_joint.GetJointAngle();
wheel_joint.SetMotorSpeed(mspeed * steer_speed);
}
}
Regards
Silver