1

Hi guys so i was trying to make this simple game in libgdx and everything was fine until i noticed that i need to apply a big force just to make the player move a little is there any way to make it need less force? This is my PlayScreen where I render the player. `

private Logang game;

//basic playscreen variables
private OrthographicCamera gamecam;
private Viewport gamePort;

//Box2d variables
private World world;
private Box2DDebugRenderer b2dr;

boolean drawn = true;
private Player p;
private int pX = 100, pY = 300;

public GameScreen(Logang game) {

    this.game = game;
    //create cam used to follow mario through cam world
    gamecam = new OrthographicCamera();
    gamecam.update();
    Box2D.init();
    //create our Box2D world, setting no gravity in X, -10 gravity in Y, and allow bodies to sleep
    world = new World(new Vector2(0, Logang.GRAVITY), true);
    //allows for debug lines of our box2d world.
    b2dr = new Box2DDebugRenderer();


    //create a FitViewport to maintain virtual aspect ratio despite screen size
    gamePort = new ScalingViewport(Scaling.fill, Logang.GWIDTH, Logang.GHEIGHT, gamecam);

    p = new Player(new Sprite(new Texture("hud_p3.png")), world, pX, pY, 1);

    //initially set our gamcam to be centered correctly at the start of of map
    gamecam.position.set(gamePort.getWorldWidth() / 2 , gamePort.getWorldHeight() / 2, 0);

    line();
}


@Override
public void show() {

}

public void update(float dt) {
    //handle user input first
    p.update(dt);
    //update our gamecam with correct coordinates after changes
}


@Override
public void render(float delta) {
    //separate our update logic from render
    update(delta);

    //Clear the game screen with Black
    Gdx.gl.glClearColor(0, 0, 0, 1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    world.step(1f / 60f, 6, 2);

    gamecam.position.set(p.getSprite().getX(),Logang.GHEIGHT / 2, 0); // x and y could be changed by Keyboard input for example

    gamecam.update();

    game.getBatch().setProjectionMatrix(gamecam.combined);

    //renderer our Box2DDebugLines
    b2dr.render(world, gamecam.combined);

    System.out.println("Player x: " + p.getSprite().getX() + " Camera X: " + gamecam.position.x + " Body X: " + p.getBody().getPosition().x);
    //System.out.println("Player y: " + p.getSprite().getY() + " Camera Y: " + gamecam.position.y + " Body Y: " + p.getBody().getPosition().y);


    game.getBatch().begin();


    if (p.getBody() != null)
        p.render(game.getBatch());

    EntityManager.renderTerra(game.getBatch(), delta);


    game.getBatch().end();

}

public void line() {
    Texture tmp = new Texture("hud_p3.png");
    tmp.setWrap(Texture.TextureWrap.MirroredRepeat, Texture.TextureWrap.MirroredRepeat);
    for (int i = 0; i < 50; i++) {
        EntityManager.add(new Ground(new Sprite(tmp), world, (int)(i * Logang.TILE), 1, 2));
    }
   // EntityManager.changeSize(((Logang.TILE) * 5),Logang.TILE);
}

@Override
public void resize(int width, int height) {
    //updated our game viewport
    gamePort.update(width, height);
}

public World getWorld() {
    return world;
}

@Override
public void pause() {

}

@Override
public void resume() {

}

@Override
public void hide() {

}

@Override
public void dispose() {
    world.dispose();
    b2dr.dispose();
}`

And this is my Entity class which is extended by the player

 private World world;
private Sprite sprite;
private Body body;
private int tipo;

public Entity(Sprite sprite, World world, int x, int y, int tipo){
    this.sprite = sprite;
    this.world = world;
    getSprite().setPosition(x, y);
    getSprite().setSize(Logang.TILE , Logang.TILE);
    define(tipo);
    this.tipo = tipo;
}

public void update(float dt){
        if(Gdx.input.isKeyPressed(Input.Keys.LEFT)){
            getBody().applyLinearImpulse(new Vector2(-Logang.PPM,0f), getBody().getWorldCenter(), true);
        }
        if(Gdx.input.isKeyPressed(Input.Keys.RIGHT)){
            getBody().applyLinearImpulse(new Vector2(Logang.PPM,0f), getBody().getWorldCenter(), true);
        }
        if(Gdx.input.isKeyPressed(Input.Keys.SPACE)){
            getBody().applyLinearImpulse(0f,-Logang.GRAVITY * Logang.PPM, getBody().getPosition().x, getBody().getPosition().y, true);
        }
    }   
}

public void define(int tipo){
    BodyDef bdef = new BodyDef();
    bdef.position.set((getSprite().getX() + getSprite().getWidth() / 2), (getSprite().getY() + getSprite().getHeight() / 2));
    switch(tipo){
        case 1: {
            bdef.type = BodyDef.BodyType.DynamicBody;
            break;
        }
        case 2:{
            bdef.type = BodyDef.BodyType.StaticBody;
            break;
        }
        case 3:{
            bdef.type = BodyDef.BodyType.DynamicBody;
            break;
        }

    }

    body = world.createBody(bdef);

    FixtureDef fdef = new FixtureDef();
    PolygonShape shape = new PolygonShape();
    shape.setAsBox(getSprite().getWidth() / 2, getSprite().getHeight() / 2);


    fdef.shape = shape;
    body.createFixture(fdef);
    body.setUserData(this);

    shape.dispose();
}

public void render(SpriteBatch batch){
    if(tipo != 2) {
        float posX = getBody().getPosition().x;
        float posY = getBody().getPosition().y;

        getSprite().setPosition(posX - getSprite().getWidth() / 2, posY - getSprite().getHeight() / 2);

    }
    getSprite().draw(batch);
}

public Sprite getSprite() {
    return sprite;
}

public void setSprite(Sprite sprite) {
    this.sprite = sprite;
}

public Body getBody() {
    return body;
}

public void setBody(Body body) {
    this.body = body;
}
}

Thank everybody for any answer

Leonardo Drici
  • 749
  • 3
  • 11
  • 32

1 Answers1

2

Box2D is a physics engine so tries to imitate real life physics in game. So if your object is large and heavy it will require a large amount of force to move it.

To make it so your objects can move with less force you can either make them smaller or change the density of them to make them lighter which will allow them to be moved with less force.

To change the density you set it in the fixtureDefinition

FixtureDef fdef = new FixtureDef();
fdef.density=0.1f; // (weight: range 0.01 to 1 is good)
fdef.friction = 0.7f; // (how slippery it is: 0=like ice 1 = like rubber)
fdef.restitution = 0.3f; //(how bouncy is it 0= not bouncy 1 = 100% bouncy)

Another thing I noticed is you are using what seems to be a PixelPerMeter ratio for your forces in this line:

getBody().applyLinearImpulse(new Vector2(-Logang.PPM,0f), getBody().getWorldCenter(), true);

You shouldn't use this value for your forces as this is for converting box2d world to render coordinates and you can use the following code to apply the force to the center.

getBody().applyLinearImpulse(new Vector2((10f*getBody().getMass()),0f), getBody().getWorldCenter(), true);

As a side note the impulse is used to create a single application of force whereas body.applyForceToCenter(force,wake); is used to apply a constant force over time. Try with the apply force method and see if this helps.

dfour
  • 1,376
  • 1
  • 12
  • 16