I am developing an off road game, and I am new to libgdx.
I made a car, with only 3 parts: chassis, rear & front wheel. I got a "Zoomable" camera bind with chassis, chassis connected to wheels with Wheel Joint.
Chassis works fine with texture but not wheels.
Here's the problems:
Focus.java
public class Focus extends InputAdapter {
private Body chassis, rearWheel, frontWheel;
private WheelJoint leftAxis, rightAxis;
private float speed = 90f;
private Sprite spriteChassis, spriteRearWheel, spriteFrontWheel;
private float xOffSet = 5f;
private float yOffSet = -2f;
private float rwOffSet = 0;
private float fwOffSet = 0;
private float rwOffSetY = 0;
private float fwOffSetY = 0;
public float getOffSetX(){ return xOffSet; }
public float getOffSetY(){ return yOffSet; }
public Focus(World world, FixtureDef chassisFixtureDef, FixtureDef wheelFixtureDef, float x, float y) {
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyDef.BodyType.DynamicBody;
bodyDef.position.set(x,y);
bodyDef.gravityScale = 1;
float width = 5.333f;
float height = 1.933f;
BodyEditorLoader loader = new BodyEditorLoader(Gdx.files.internal("data/focus.json"));
chassis = world.createBody(bodyDef);
loader.attachFixture(chassis, "focus", chassisFixtureDef, width);
String imgpath = loader.getImagePath("focus");
chassis.createFixture(chassisFixtureDef);
chassis.setGravityScale(1.2f);
spriteChassis = new Sprite(new Texture(imgpath));
spriteRearWheel = new Sprite(new Texture("tires.png"));
spriteFrontWheel = new Sprite(new Texture("tires.png"));
// Wheels
CircleShape wheelShape = new CircleShape();
wheelShape.setRadius(height / 6f);
wheelFixtureDef.shape = wheelShape;
rearWheel = world.createBody(bodyDef);
rearWheel.createFixture(wheelFixtureDef);
frontWheel = world.createBody(bodyDef);
frontWheel.createFixture(wheelFixtureDef);
// Axels
WheelJointDef axisDef = new WheelJointDef();
axisDef.bodyA = chassis;
axisDef.bodyB = rearWheel;
rwOffSet = wheelShape.getRadius()*3.3f;
axisDef.localAnchorA.x = rwOffSet;
rwOffSetY = height/10.5f;
axisDef.localAnchorA.y = rwOffSetY;
axisDef.frequencyHz = chassisFixtureDef.density;
axisDef.localAxisA.set(Vector2.Y);
axisDef.maxMotorTorque = chassisFixtureDef.density * 24.5f;
leftAxis = (WheelJoint) world.createJoint(axisDef);
// right
// Axels
WheelJointDef axisDef2 = new WheelJointDef();
axisDef2.bodyA = chassis;
axisDef2.bodyB = frontWheel;
axisDef2.localAnchorA.set(width, 0);
axisDef2.frequencyHz = chassisFixtureDef.density;
axisDef2.localAxisA.set(Vector2.Y);
fwOffSet = width-wheelShape.getRadius()*3.f;
axisDef2.localAnchorA.x = fwOffSet;
fwOffSetY = height/9f;
axisDef.localAnchorA.y = fwOffSetY;
axisDef2.maxMotorTorque = chassisFixtureDef.density * 24.5f;
rightAxis = (WheelJoint) world.createJoint(axisDef2);
}
@Override
public boolean keyDown(int keycode) {
switch(keycode) {
case Input.Keys.W:
leftAxis.enableMotor(false);
rightAxis.enableMotor(true);
rightAxis.setMotorSpeed(-speed);
break;
case Input.Keys.S:
leftAxis.enableMotor(false);
rightAxis.enableMotor(true);
rightAxis.setMotorSpeed(speed);
break;
case Input.Keys.SPACE:
leftAxis.enableMotor(true);
leftAxis.setMotorSpeed(0);
rightAxis.enableMotor(true);
rightAxis.setMotorSpeed(0);
break;
}
return true;
}
@Override
public boolean keyUp(int keycode) {
switch(keycode) {
case Input.Keys.SPACE:
case Input.Keys.W:
case Input.Keys.S:
leftAxis.enableMotor(false);
rightAxis.enableMotor(false);
break;
}
return true;
}
public Sprite getSpriteChassis(){ return spriteChassis; }
public Sprite getSpriteRearWheel() { return spriteRearWheel; }
public Sprite getSpriteFrontWheel() { return spriteFrontWheel; }
public Body getChassis() { return chassis; }
public Body getFrontWheel() { return frontWheel; }
public Body getRearWheel() { return rearWheel; }
}
SmallHill.java (Screen)
public class SmallHill implements Screen {
private final float PIXELS_PER_METER = 15f; // how many pixels to a meter
private final float TIME_STEP = 1 / 60f; // 60 fps
private final float SPEED = 1 / 60f; // speed constant
private final float MIN_ZOOM = .25f; // How far in should we be able to zoom
private final float ANGULAR_MOMENTUM = .5f;
private final int VELOCITY_ITERATIONS = 8; // copied from box2d example
private final int POSITION_ITERATIONS = 3; // copied from box2d example
private World world;
private Box2DDebugRenderer debugRenderer;
private OrthographicCamera camera;
private Body ball;
private Focus focus;
private BitmapFont font;
private SpriteBatch batch;
private Texture texture;
@Override
public void show() {
batch = new SpriteBatch();
font = new BitmapFont();
font.setColor(Color.RED);
world = new World(new Vector2(0, -9.81f), true);
debugRenderer = new Box2DDebugRenderer();
camera = new OrthographicCamera();
camera.zoom = 1f;
BodyDef bodyDef = new BodyDef();
// Shape
ChainShape groundShape = new ChainShape();
groundShape.createChain(new Vector2[] {new Vector2(-1,24),new Vector2(0,14),new Vector2(25,14),new Vector2(50,10),new Vector2(100,5),new Vector2(150,12),new Vector2(155,10), new Vector2(200,22),new Vector2(225,22),new Vector2(226,22.15f),new Vector2(227,22),new Vector2(229,22.25f),new Vector2(350,22),new Vector2(385,24),new Vector2(389,25),new Vector2(390,24),new Vector2(395,25),new Vector2(398,24),new Vector2(400,25),new Vector2(401,48) });
CircleShape ballShape = new CircleShape();
ballShape.setRadius(1f);
ballShape.setPosition(new Vector2(-10, 16));
// Fixture
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = groundShape;
fixtureDef.friction = .8f;
fixtureDef.restitution = 0;
world.createBody(bodyDef).createFixture(fixtureDef);
fixtureDef.shape = ballShape;
fixtureDef.friction = 0.9f;
fixtureDef.restitution = .3f;
fixtureDef.density = 3;
bodyDef.type = BodyType.DynamicBody;
fixtureDef.density = 5;
fixtureDef.friction = .4f;
fixtureDef.restitution = .1f;
FixtureDef wheelFixtureDef = new FixtureDef();
wheelFixtureDef.density = fixtureDef.density ;
wheelFixtureDef.friction = 2;
wheelFixtureDef.restitution = .7f;
focus = new Focus(world, fixtureDef, wheelFixtureDef, 50, 14);
wheelFixtureDef.shape.dispose();
fixtureDef.shape.dispose();
Gdx.input.setInputProcessor(new InputMultiplexer(new InputController() {
@Override
public boolean keyDown(int keycode) {
switch(keycode) {
case Input.Keys.ESCAPE:
dispose();
break;
case Input.Keys.R:
camera.zoom = 1;
break;
case Input.Keys.PLUS:
camera.zoom = 10;
break;
case Input.Keys.MINUS:
camera.zoom = 1;
break;
}
return false;
}
@Override
public boolean scrolled(int amount) {
if(amount == -1 && camera.zoom <= MIN_ZOOM) {
camera.zoom = MIN_ZOOM;
} else {
camera.zoom += amount / PIXELS_PER_METER;
}
return false;
}
},focus));
}
@Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
world.step(TIME_STEP, VELOCITY_ITERATIONS, POSITION_ITERATIONS);
camera.position.set(focus.getChassis().getWorldCenter().x,focus.getChassis().getWorldCenter().y,0);
camera.update();
String x;
WheelJoint wj = (WheelJoint) focus.getChassis().getJointList().get(0).joint;
x = (int)Math.abs(wj.getJointSpeed())+"";
batch.begin();
font.draw(batch, x, 20, 20);
focus.getSpriteChassis().setPosition((Gdx.graphics.getWidth() / 2 - focus.getSpriteChassis().getWidth() / 2) + focus.getOffSetX(), (Gdx.graphics.getHeight() / 2 - focus.getSpriteChassis().getHeight() / 2) + focus.getOffSetY());
focus.getSpriteChassis().setRotation(focus.getChassis().getAngle() * MathUtils.radiansToDegrees);
focus.getSpriteChassis().setScale(1/camera.zoom);
focus.getSpriteChassis().draw(batch);
focus.getSpriteRearWheel().setPosition((Gdx.graphics.getWidth() / 2 - focus.getSpriteChassis().getWidth() / 2) , (Gdx.graphics.getHeight() / 2 - focus.getSpriteChassis().getHeight() / 2) );
focus.getSpriteFrontWheel().setPosition((Gdx.graphics.getWidth() / 2 - focus.getSpriteChassis().getWidth() / 2) , (Gdx.graphics.getHeight() / 2 - focus.getSpriteChassis().getHeight() / 2) );
//focus.getSpriteRearWheel().setPosition((Gdx.graphics.getWidth() / 2 - focus.getSpriteChassis().getWidth() / 2) + focus.getRwOffSet()*PIXELS_PER_METER*(1/camera.zoom), (Gdx.graphics.getHeight() / 2 - focus.getSpriteChassis().getHeight() / 2) + focus.getRwOffSetY()*PIXELS_PER_METER*(1/camera.zoom) );
//focus.getSpriteFrontWheel().setPosition((Gdx.graphics.getWidth() / 2 - focus.getSpriteChassis().getWidth() / 2)+ focus.getFwOffSet()*PIXELS_PER_METER*(1/camera.zoom) , (Gdx.graphics.getHeight() / 2 - focus.getSpriteChassis().getHeight() / 2) + focus.getFwOffSetY()*PIXELS_PER_METER*(1/camera.zoom));
focus.getSpriteRearWheel().setRotation(focus.getRearWheel().getAngle() * MathUtils.radiansToDegrees);
focus.getSpriteFrontWheel().setRotation(focus.getFrontWheel().getAngle() * MathUtils.radiansToDegrees);
focus.getSpriteRearWheel().setScale(1 / camera.zoom);
focus.getSpriteRearWheel().draw(batch);
focus.getSpriteFrontWheel().setScale(1 / camera.zoom);
focus.getSpriteFrontWheel().draw(batch);
batch.end();
debugRenderer.render(world, camera.combined);
}
@Override
public void resize(int width, int height) {
camera.viewportWidth = width / PIXELS_PER_METER;
camera.viewportHeight = height / PIXELS_PER_METER;
}
@Override
public void hide() { dispose(); }
@Override
public void pause() { }
@Override
public void resume() { }
@Override
public void dispose() {
world.dispose();
debugRenderer.dispose();
batch.dispose();
font.dispose();
}
}
Can anyone help me understand? many thanks !!!
Box2D has a speed limit, which is about 2.0 units/timestep.
So if you step 60 times / second, you can move 2 * 60 = 120 units/second.
To increase the maximum speed you can decrease the timestep ie increase the number of steps/second.
If you, for example, increase it to 30, you can move up to 2 * 120 = 240 units/second.
Also make sure, that you are using meters as your unit. Box2D has been created with kg, meters and seconds in mind, so you should also use those units.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.