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:
I can't figure out how to calculate the √(correct) vector2 of wheels to put it in the [Sprite.setPosition] method
How to make my car faster cause it never >94
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 i.e. 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.
Related
I am a new Android game developer. I want to force my game object which moves to projectile trajectory like in Angry birds.
Related example here and my example You can see image.
I use jbox2d little bit code, but I don't know how to make it work.
private static class ProjectileEquation {
public float gravity;
public Vector2 startVelocity = new Vector2();
public Vector2 startPoint = new Vector2();
public float yogx(float t) {
return startPoint.x + t * startVelocity.x;
}
public float yogy(float t) {
float u = (float) -4.97741939970554;
float v = (float) 30.88079;
float tt = 1/6f;
float n = (u+v)/2*tt;
return startPoint.y + n * t *startVelocity.y + 0.5f *(n*n+n)
* t * t * gravity;
}
}
private static class Controller {
public float power = -66f;
public float angle = 585f;
}
}
public float P2M(float xPixels) {
return xPixels * metersPerPixel;
}
public float M2P(float xMetres) {
return xMetres * pixelsPerMeter;
}
public float MaxHeight(){
if (projectileEquation.startVelocity.y > 0){
return projectileEquation.startPoint.y;
}
return projectileEquation.startPoint.y;
}
public void Update() {
projectileEquation.startVelocity.set(controller.power,controller.power);
projectileEquation.startVelocity.rotate(controller.angle);
// bd = bodies;
}
#Override
protected void onDraw(Canvas c) {
super.onDraw(c);
MaxHeight();
Update();
float t = 0f;
x = c.getWidth()/2;
y = c.getHeight()-20;
float timeSeparation = this.timeSeparation;
for (int i = 0; i < trajectoryPointCount; i++) {
float x = this.x + projectileEquation.yogx(t);
float y = this.y + -projectileEquation.yogy(t);
t += timeSeparation;
if(A) {
c.drawBitmap(bmp, x, y, null);
}else if(B) {
float bX = M2P(body.getPosition().x);
float by = c.getHeight() - M2P(body.getPosition().y);
body.setActive(true);
c.drawCircle(bX, by, M2P(body.m_fixtureList.m_shape.m_radius), circlePaint);
}
}
}
public class jbox2d {
public float targetFps = 30.0f;
public float timeStep = (1.0f / targetFps);
private int interations = 2;
public Body body;
private World world;
private BodyDef bodydef;
public void Create(){
Vec2 gravity = new Vec2(0,-10f);
boolean doSleep = true;
world = new World(gravity, doSleep);
}
public void addboll() {
bodydef = new BodyDef();
bodydef.type = BodyType.DYNAMIC;
bodydef.allowSleep = true;
bodydef.position.set(8.24f,10f);
body = world.createBody(bodydef);
body.setActive(false);
float tt = 0f;
Vec2 stx = new Vec2();
Vec2 sty =new Vec2();
for (int it = 0; it < 20; it++) {
stx = M2P(projectileEquation.startVelocity.x);
sty = M2P(projectileEquation.startVelocity.y);
stx = M2P(projectileEquation.yogx(tt));
sty = -M2P(projectileEquation.yogy(tt));
body.setLinearVelocity(new Vec2(stx,sty));
body.applyLinearImpulse(body.getLinearVelocity(), body.getWorldCenter());
tt += timeSeparation;
}
CircleShape circle = new CircleShape();
circle.m_radius = (float).42;
FixtureDef fixturedef = new FixtureDef();
fixturedef.density = 1.0f;
fixturedef.restitution = 0.9f;
fixturedef.friction = 0.2f;
fixturedef.shape = circle;
body.createFixture(fixturedef);
}
public void update(){
world.step(timeStep, interations, interations);
}
}
I have made an engine with LWJGL and I am pleased with it so far. Naturally I am now ready to add physics to the engine so I can actually start creating a game with it. I have chosen to use Jbox2D as it seems fairly flexible and I have imported it into the project and done all the setup needed, however after implementing the body system into my GameObject class and running the game all GameObjects seemed to go to the centre of the window, I believe I may have made some mistakes in the code:
private BodyDef bodyDef = new BodyDef();
private Body box = world.createBody(bodyDef);
public float MOVE_SPEED = 7.0f;
public TAG tag;
public static int direction = 0;
public int jumpsRemaining;
public float xSpeed = MOVE_SPEED;
public float ySpeed = MOVE_SPEED;
public float x, y;
public float sX = 32, sY = 32;
public boolean jumpPressed, jumpWasPressed;
public boolean jumping = false;
public boolean falling = true;
//public int collidingX = 0;
//public int collidingY = 0;
public Time time = new Time();
protected static final int UP = 1;
protected static final int RIGHT = 2;
protected static final int DOWN = 3;
protected static final int LEFT = 4;
private boolean left = true;
private boolean right = true;
private boolean up = true;
private boolean down = true;
private Sprite spr;
public GameObject(float sX, float sY, float posX, float posY, BodyType type) {
this.sX = sX;
this.sY = sY;
this.x = posX;
this.y = posY;
initPhysics(type);
}
public GameObject(float posX, float posY, BodyType type) {
this.x = posX;
this.y = posY;
initPhysics(type);
}
public abstract void update();
public abstract void input();
private void initPhysics(BodyType type){
bodyDef.type = type;
bodyDef.position.set(x/30,y/30);
PolygonShape boxShape = new PolygonShape();
boxShape.setAsBox(sX/30/2, sY/30/2);
FixtureDef fixture = new FixtureDef();
fixture.density = 1;
fixture.shape = boxShape;
box.createFixture(fixture);
physicsBodies.add(box);
}
/**protected GameObject Colliding() {
for (GameObject gob : gameObjects) {
if (gob != this) {
if (Collision.checkCollision(gob, this) != null) {
return gob;
}
}
}
return null;
}**/
public void render() {
if (spr != null) {
glPushMatrix();
{
glTranslatef(box.getPosition().x * 30, box.getPosition().y * 30, 0);
spr.renderSprite();
}
glPopMatrix();
}
}
public void setTexture(String tex) {
spr = new Sprite(sX, sY, tex);
}
the world and body hashSet are in the main class if you are wondering, I think I have severely screwed up the code somehow. Also I am using the legacy pipeline of lwjgl as it is simpler and fits the engine better.
I simply set the origin of my sprites to their centre rather than the bottom left and that solved the problem, like this:
glVertex2f(-sX / 2, -sY / 2);
glTexCoord2f(0, 0);
glVertex2f(-sX / 2, sY / 2);
glTexCoord2f(1, 0);
glVertex2f(sX / 2, sY / 2);
glTexCoord2f(1, 1);
glVertex2f(sX / 2, -sY / 2);
glTexCoord2f(0, 1);
I hope this helps anyone in a similar situation (sX is size X, sY is sizeY)
I have this problem where when I play this certain music with libgdx, I start hearing some soft popping noise in the background while the music is played. I have tried some different audio formats but It doesn't help. In my code the music is the "endmusic".
Here is my whole code:
public class WorldScreen implements Screen{
Preferences prefs;
private Texture bgCity;
private Texture bgLoop;
private Texture bgEnd;
private Texture bgFade;
private Texture hud;
public static OrthographicCamera camera;
SpriteBatch batch;
Rectangle player;
Rectangle background;
Rectangle backgroundloop;
public float time = 100;
public float camx = 0;
public float camy = 0;
public static float score = 384400000f;
public static float value = 384400000f;
BitmapFont font;
GestureListenerC controller;
private Music startmusic;
private static Music loopmusic;
private Music endMusic;
public static boolean ending = false;
private int endint;
private String endstring = "";
public WorldScreen(final JetpackGame aa) {
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camx = camera.viewportWidth / 2f;
camy = camera.viewportHeight / 2f;
controller.update();
camera.update();
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(bgCity, background.x, background.y);
batch.draw(bgLoop, backgroundloop.x, backgroundloop.y);
batch.draw(bgEnd, 0, 5360);
if(!ending){
if(camera.position.y >= 5360) camera.position.y = 4096;
}
if(value <= 0) ending = true;
//ENDING
if(ending){
time += 0.1f * Gdx.graphics.getDeltaTime();
startmusic.stop();
loopmusic.stop();
if(time <= 102.75f){
camera.position.y += 0.1 * time;
if(camera.position.y >= 5360) camera.position.y = 4096;
}
if(time >= 102.75f) {
if (camera.position.y >= 4090 && camera.position.y <= 6666)
camera.position.y += 0.1 * time;
}
endMusic.play();
font.setScale(2.0f);
font.draw(batch, "You already finished the game xD", 0,1200);
if(time >= 103.2f)endMusic.stop();
}
Matrix4 normalProjection = new Matrix4().setToOrtho2D(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batch.setProjectionMatrix(normalProjection);
batch.draw(hud, 0, 85, Gdx.graphics.getWidth(), 1200);
font.setScale(3.5f);
if(time <=102.5f) {
font.draw(batch, ">Meters to the moon", 10, 1260);
font.draw(batch, ">" + (int)value + "m", 10, 1190);
}
//font.draw(batch,""+time, 100, 100);
//font.draw(batch,""+value, 100,120);
if(time >= 103) {
font.setScale(3.0f);
font.draw(batch, ">"+endstring, 10,1200);
}
if(time >= 104)
batch.draw(bgFade, 0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batch.end();
if(value < 0) value = 0;
if(!startmusic.isPlaying()) {
loopmusic.setLooping(true);
loopmusic.play();
}
//RANDOM ENDING GENERATOR
switch(endint){
case 1: endstring = "Now do it again faster!";
break;
case 2: endstring = "What are you doing with your life?!";
break;
case 3: endstring = "Do you want a cookie?";
break;
case 4: endstring = "How many hours did you waste?";
break;
case 5: endstring = "So you have no life?";
break;
case 6: endstring = "Now get out of your room and go outside!";
break;
}
}
#Override
public void resize(int width, int height) {
}
#Override
public void show() {
Random rand = new Random();
endint = rand.nextInt(6);
font = new BitmapFont();
font.setColor(Color.GREEN);
Preferences prefs = Gdx.app.getPreferences("My Preferences");
float value = prefs.getFloat("Value", 384400000f);
controller = new GestureListenerC();
GestureDetector gestureDetector = new GestureDetector(20, 0.5f, 2, 0.15f, controller);
Gdx.input.setInputProcessor(gestureDetector);
loopmusic = Gdx.audio.newMusic(Gdx.files.internal("audio/AmbientLoop.ogg"));
startmusic = Gdx.audio.newMusic(Gdx.files.internal("audio/AmbientStart.ogg"));
endMusic = Gdx.audio.newMusic(Gdx.files.internal("audio/Moon.ogg"));
endMusic.setLooping(false);
startmusic.play();
bgCity = new Texture(Gdx.files.internal("img/city_BG.png"));
bgLoop = new Texture(Gdx.files.internal("img/loopBG.png"));
bgEnd = new Texture(Gdx.files.internal("img/endBG.png"));
bgFade = new Texture(Gdx.files.internal("img/fade.png"));
hud = new Texture(Gdx.files.internal("img/Hud.png"));
camera = new OrthographicCamera();
camera.setToOrtho(false, 480,854);
batch = new SpriteBatch();
background = new Rectangle();
background.x = 0;
background.y = 0;
background.width = 479;
background.height = 4096;
backgroundloop = new Rectangle();
backgroundloop.x = 0;
backgroundloop.y = 4096;
backgroundloop.width = 512;
backgroundloop.height = 1024;
}
#Override
public void hide() {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
prefs.putFloat("Value", value);
prefs.flush();
batch.dispose();
font.dispose();
bgCity.dispose();
bgLoop.dispose();
bgEnd.dispose();
bgFade.dispose();
hud.dispose();
loopmusic.dispose();
startmusic.dispose();
endMusic.dispose();
}
}
Basically i have a circle object which acts as the player, and it can only jump. What I want to do is make the circle object keep rolling while having a constant gravity or force act on the circle object to make it keep rolling to the right on the ground. I have tried making a constant gravity by setting the vector2 x value to 0.5f:
World world = new World(new Vector2(0.5f, -9.8f), true);
When i do this the ball rapidly keeps moving faster as time goes on.
Is there way I can achieve my desired effect?
Play class code:
public class Play implements Screen,ContactListener{
World world = new World(new Vector2(0f, -9.8f), true);
Box2DDebugRenderer debugRenderer;
OrthographicCamera camera;
static final int PPM = 100;
static float height,width;
Body player;
RayHandler handler;
PointLight l1;
Body groundBody;
float tileSize;
boolean playerOnGround = false;
int footContact;
ShapeRenderer shapeRenderer;
PointLight light;
TiledMap tileMap;
OrthogonalTiledMapRenderer tmr;
BallJump game;
int level;
Color lightColor = new Color();
public Play(int level,BallJump game ) {
this.level = level;
this.game = game;
}
#Override
public void show() {
shapeRenderer = new ShapeRenderer();
height = Gdx.graphics.getHeight();
width = Gdx.graphics.getWidth();
//set camera
camera = new OrthographicCamera();
new FitViewport(width/PPM/2, height/PPM/2, camera);
if((height + width) > 1500 && (height + width) < 2000) {
camera.zoom = 0.5f;
} else if ((height + width) > 2000) {
camera.zoom = 0.75f;
}
camera.update();
//player Body
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.DynamicBody;
bodyDef.position.set((width/PPM)/2/2, (height / PPM)/2/2);
player = world.createBody(bodyDef);
CircleShape dynamicCircle = new CircleShape();
dynamicCircle.setRadius(5f/PPM);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = dynamicCircle;
fixtureDef.density = 0.4f;
fixtureDef.friction = 1f;
fixtureDef.restitution = 0f;
player.createFixture(fixtureDef).setUserData("player");;
debugRenderer = new Box2DDebugRenderer();
//Lighting
handler = new RayHandler(world);
light = new PointLight(handler,500,Color.MAGENTA,4f,width/PPM/2/2/2,height/PPM/2/2);
light.attachToBody(player);
// tile map
tileMap = new TmxMapLoader().load("test2.tmx");
tmr = new OrthogonalTiledMapRenderer(tileMap,0.01f);
TiledMapTileLayer layer = (TiledMapTileLayer) tileMap.getLayers().get("block");
tileSize = layer.getTileHeight()*2;
for(int row = 0; row < layer.getHeight(); row++) {
for(int col = 0; col < layer.getWidth(); col++) {
Cell cell = layer.getCell(col, row);
if(cell == null) { continue;}
if(cell.getTile() == null) { continue;}
BodyDef bdef = new BodyDef();
bdef.type = BodyType.StaticBody;
bdef.position.set((col + 0.5f) * tileSize /PPM/2, (row + 0.5f) * tileSize /PPM/2);
PolygonShape cs = new PolygonShape();
cs.setAsBox(tileSize/2/PPM/2, tileSize/2/PPM/2);
FixtureDef fdef = new FixtureDef();
fdef.friction = 0f;
fdef.shape = cs;
world.createBody(bdef).createFixture(fdef).setUserData("ground");;
world.setContactListener(this);
}
}
}
public void update() {
playerOnGround = footContact > 0;
if(Gdx.input.isKeyJustPressed(Keys.UP) || (Gdx.input.isTouched())) {
if(playerOnGround)
player.applyForceToCenter(0, 0.75f, true);
}
else if (Gdx.input.isKeyPressed(Keys.SPACE)) {
player.setTransform((width/PPM)/2/2, (height / PPM)/2/2, 0);
}
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void beginContact(Contact contact) {
Fixture a = contact.getFixtureA();
Fixture b = contact.getFixtureB();
if(b.getUserData().equals("player") && b.getUserData() != null) {
footContact++;
player.setAngularDamping(5f);
}
if(a.getUserData().equals("player") && a.getUserData() != null) {
footContact++;
player.setAngularDamping(5f);
}
}
#Override
public void endContact(Contact contact) {
Fixture a = contact.getFixtureA();
Fixture b = contact.getFixtureB();
if(b.getUserData().equals("player") && b.getUserData() != null) {
footContact--;
}
if(a.getUserData().equals("player") && a.getUserData() != null) {
footContact--;
}
}
#Override
public void preSolve(Contact contact, Manifold oldManifold) {}
#Override
public void postSolve(Contact contact, ContactImpulse impulse) {}
#Override
public void render(float delta) {
camera.position.set(player.getPosition().x, player.getPosition().y, 0);
update();
camera.update();
shapeRenderer.setProjectionMatrix(camera.combined);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
world.step(1/60f, 6, 2);
handler.updateAndRender();
handler.setCombinedMatrix(camera.combined);
debugRenderer.render(world, camera.combined);
}
}
The gravity is a force, which is applied to every (dynamic) body in the world in every step.
That means, that the velocity of those affected object increases every frame.
Thats just the expected result, think about the reality:
If you jump from a high place, you get faster and faster, until you hit the ground (or air resistance limits your speed).
If you want to move with a constant speed (in Box2D), you should do something like that:
Vector2 vel = this.player.body.getLinearVelocity();
if (vel.x < MAX_VELOCITY) {
circle.applyLinearImpulse(impulse.x, impulse.y, pos.x, pos.y, wake);
Where impulse.x is a float, defining the impulse strength applyed in x-direction, impulse.y is the same for y-direction, pos.x and pos.y is the position, to which you want to apply the impulse (if not the center, the body will get some torque-effect) and the boolean wake defines, if the body should wake up.
i'm trying to make a program with Box2D and libgdx that makes the character jump on a static body (here, a circle). But my camera (that is following the dynamic body (the player)) keeps going down, even if my character stays on top of the circle as intended. So my questions are :
1) Why my camera keeps falling down, when it's supposed to follow the "playerBody" that is staying on top of the static body ?
2) Why my camera bounce when I press the Z key, but not my playerbody ?
Thanks in advance. You may try to run it in eclipse, to see better what I mean, here's what I put in my Activity class :
(I got no errors/warnings at all.)
//private SpriteBatch batch;
//private Texture texture;
//private Sprite sprite;
//public Body body;
World world;
Body playerBody;
Body planetBody;
CircleShape planetCircle;
PolygonShape playerBox;
OrthographicCamera camera;
Box2DDebugRenderer debugRenderer;
static final float BOX_STEP=1/60f;
static final int BOX_VELOCITY_ITERATIONS=6;
static final int BOX_POSITION_ITERATIONS=2;
static final float WORLD_TO_BOX=0.01f;
static final float BOX_WORLD_TO=100f;
boolean jump = false;
long lastGroundTime = 0;
#Override
public void create() {
world = new World(new Vector2(0, -50), true);
debugRenderer = new Box2DDebugRenderer();
camera = new OrthographicCamera();
camera.viewportHeight = 320;
camera.viewportWidth = 480;
camera.position.set(camera.viewportWidth * .5f, camera.viewportHeight * .5f, 0f);
camera.update();
//Ground body
/*BodyDef groundBodyDef =new BodyDef();
groundBodyDef.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2 - 100 + 125);
Body groundBody = world.createBody(groundBodyDef);
PolygonShape groundBox = new PolygonShape();
groundBox.setAsBox((camera.viewportWidth) * 2, 10.0f);
groundBody.createFixture(groundBox, 0.0f);
*/
//Planet
BodyDef planetDef = new BodyDef();
planetDef.type = BodyType.StaticBody;
planetDef.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2 - 100);
Body planetBody = world.createBody(planetDef);
CircleShape planetCircle = new CircleShape();
planetCircle.setRadius(125f);
FixtureDef planetFixtureDef = new FixtureDef();
planetFixtureDef.shape = planetCircle;
planetFixtureDef.density = 1.0f;
//planetFixtureDef.friction = 0.0f;
//planetFixtureDef.restitution = 0;
planetBody.createFixture(planetFixtureDef);
//Player
BodyDef playerBodyDef = new BodyDef();
playerBodyDef.type = BodyType.DynamicBody;
playerBodyDef.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2 - 100 + 125 + 50);
playerBody = world.createBody(playerBodyDef);
PolygonShape playerBox = new PolygonShape();
playerBox.setAsBox(5.0f, 15.0f);
FixtureDef playerFixtureDef = new FixtureDef();
playerFixtureDef.shape = playerBox;
playerFixtureDef.density = 1.0f;
//playerFixtureDef.friction = 1.0f;
//playerFixtureDef.restitution = 1;
playerBody.createFixture(playerFixtureDef);
playerBody = world.createBody(playerBodyDef);
//Dynamic Body
/*BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.DynamicBody;
bodyDef.position.set(camera.viewportWidth / 2, camera.viewportHeight / 2);
Body body = world.createBody(bodyDef);
CircleShape dynamicCircle = new CircleShape();
dynamicCircle.setRadius(5f);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = dynamicCircle;
fixtureDef.density = 1.0f;
fixtureDef.friction = 0.0f;
fixtureDef.restitution = 1;
body.createFixture(fixtureDef); */
Gdx.input.setInputProcessor(this);
}
#Override
public void dispose() {
/*batch.dispose();
texture.dispose();*/
/*dynamicCircle.dispose();
groundBox.dispose();*/
playerBox.dispose();
planetCircle.dispose();
}
#Override
public void render() {
//Gdx.gl.glClearColor(1, 1, 1, 1);
update();
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
/*batch.setProjectionMatrix(camera.combined);
batch.begin();
//sprite.draw(batch);
batch.end();*/
camera.position.set(playerBody.getPosition().x, playerBody.getPosition().y, 0);
camera.update();
//camera.apply(Gdx.gl10);
debugRenderer.render(world, camera.combined);
world.step(BOX_STEP, BOX_VELOCITY_ITERATIONS, BOX_POSITION_ITERATIONS);
//playerBody.setAwake(true);
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
public void update()
{
if(jump == true /*Gdx.input.isKeyPressed(Gdx.input.)*/ && grounded() == true)
{
playerBody.setLinearVelocity(0, 0);
playerBody.applyLinearImpulse(new Vector2(0,150), new Vector2(playerBody.getPosition().x, playerBody.getPosition().y));
jump = false;
}
//playerBody.setTransform(new Vector2(camera.viewportWidth / 2, playerBody.getPosition().y), playerBody.getAngle());
//planetBody.setTransform(new Vector2(camera.viewportWidth / 2, camera.viewportHeight / 2), 0);
}
#Override
public void resume() {
}
#Override
public boolean keyDown(int keycode) {
//if(keycode == Keys.S)
return false;
}
#Override
public boolean keyUp(int keycode) {
if(keycode == Keys.Z)
jump = true;
return false;
}
public boolean grounded()
{
if(playerBody.getPosition().y <= ((camera.viewportHeight / 2) - 100 + 125))
{
return true;
}
else
{
return false;
}
}
You are creating two playerBody in the world. The second one is assigned but has no fixture. This is the one you are manipulating in your code and your camera is following. Remove the second playerBody = world.createBody(playerBodyDef); and it should work (better).