im currently programming a 2d top down racing game with box2d and libgdx.
i have a car body to which there are 4 wheels attached. these 4 wheels are attached with RevoluteJoints ( for the front wheels ) and PrismaticJoints ( for the back wheels ).
it is working pretty good except for the fact that when you get to high velocities ( nearly to the maximum the car can be accelerated to ) the wheels or the axis seem to spasm out. they start rotating the whole time. this also happens when i crash with something but in this situation it is fine to me.
here is my source code for the carwheel class. if you need anything else ill happily provide that
private Body wheelBody;
private RevoluteJoint joint;
public CarWheel(Vector2 positionCarFront, double d, double e)
{
BodyDef bd = new BodyDef();
bd.position.set(positionCarFront.add((float) d, (float) e));
bd.type = BodyType.DynamicBody;
wheelBody = Physics.createBody(bd);
PolygonShape shape = new PolygonShape();
shape.setAsBox(0.2f,0.5f);
FixtureDef wheelFixture = new FixtureDef();
wheelFixture.shape = shape;
wheelFixture.restitution = 0f;
wheelFixture.density = 1f;
wheelBody.createFixture(wheelFixture);
shape.dispose();
}
public Vector2 getPosition()
{
return wheelBody.getPosition();
}
public void createFrontJoint( Body body)
{
RevoluteJointDef rjd = new RevoluteJointDef();
rjd.initialize(body, wheelBody, wheelBody.getWorldCenter());
rjd.enableMotor = true;
rjd.maxMotorTorque = 100;
joint = (RevoluteJoint) Physics.world.createJoint(rjd);
}
public void createBackJoint( Body body)
{
PrismaticJointDef pjd = new PrismaticJointDef();
pjd.initialize(body, wheelBody, wheelBody.getWorldCenter(), new Vector2(1,0));
pjd.enableLimit = true;
pjd.lowerTranslation = 0f;
pjd.upperTranslation = 0f;
Physics.world.createJoint(pjd);
}
public void update(float engineSpeed, float steeringAngle)
{
Physics.killOrthogonalVelocity(wheelBody, 0f);
Vector2 direction = new Vector2((float) Math.sin(wheelBody.getAngle()), (float) -Math.cos(wheelBody.getAngle()));
wheelBody.applyForce(direction.scl(engineSpeed), wheelBody.getWorldCenter(), true);
if( joint != null){
float angle = steeringAngle - joint.getJointAngle();
joint.setMotorSpeed((float) (angle * CarConstants.STEER_SPEED)) ;
}
}
public void update()
{
Physics.killOrthogonalVelocity(wheelBody, 0f);
}
public Body getBody() {
// TODO Auto-generated method stub
return wheelBody;
}
public void dispose() {
Physics.world.destroyBody(wheelBody);
}
}
here is the killorthogonalvelocity method ( i copied that one from a tutorial but had to convert to java )
public static void killOrthogonalVelocity(Body body, float magnitude)
{
Vector2 currentRightNormal = body.getWorldVector( new Vector2(1,0));
Vector2 velocity = body.getLinearVelocity();
float dotRight = currentRightNormal.x * velocity.x + currentRightNormal.y * velocity.y ;
Vector2 lateral = currentRightNormal.scl(dotRight);
Vector2 impulse = lateral.scl(-1*body.getMass());
if ( impulse.len() > 0.5)
impulse.scl(0.5f/impulse.len());
body.applyLinearImpulse(impulse, body.getWorldCenter(), true );
body.applyAngularImpulse( 0.1f * body.getInertia() * -body.getAngularVelocity(), true);
}
note that the backwheels call the simple update method while the front wheels call the one with the angle
thanks for helping me. i dont know if i can provide a video of the rotating movement of the car so if you need any more information just write it here