Jakub Mateusiak
Jakub Mateusiak

Reputation: 99

LIBGDX Smoothing player movement

I have a problem with my game (jumper type game), when a player is falling down or move left/right it isn't smooth, I can see sprite multiple times (like some kind of shadow). After searching the internet I think it's something with deltaTime but I cannot find out how to fix it. The code for render method in play screen is:

@Override
public void render(float delta) {
    Gdx.gl.glClearColor(0,0,0,1);
    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

    //game running
    if(state == RUNNING){
        //make world step
        doPhysicsStep(delta);
    //update player and camera
        player.update(delta);
    if(player.getBody().getPosition().x < bottomLeft.x)
        player.getBody().setTransform(bottomRight.x, player.getBody().getPosition().y, player.getBody().getAngle());
    else if(player.getBody().getPosition().x > bottomRight.x)
        player.getBody().setTransform(bottomLeft.x, player.getBody().getPosition().y, player.getBody().getAngle());

    camera.position.y =player.getBody().getPosition().y > camera.position.y ? player.getBody().getPosition().y: camera.position.y;
    camera.update();
    levelGenerator.generate(camera.position.y + camera.viewportHeight /2,camera.position.y - camera.viewportHeight /2);
    }

    //game ended
    if(player.getBody().getPosition().y< camera.position.y - camera.viewportHeight/2 -player.HEIGHT/2 && state == RUNNING){
        gameOverScreen.updateScore(score.getText().toString().substring(7));
        state = END;
    }
    if(state == END){
        gameOverScreen.setVisible(true);
    }
    //drawing game
    batch.setProjectionMatrix(camera.combined);
    batch.begin();
    renderBackground();
    renderPlatform();
    renderPlayer();
    Assets.sparks.draw(batch, delta);
    batch.end();
}

public void renderPlatform(){
    //world.getBodies(tmpBodies);
    //for(Body body : tmpBodies)
    //  if(body.getUserData() != null && body.getUserData() instanceof Platform)
            for(int i=0;i<platforms.size();i++){

            Body body = platforms.get(i).getBody();
            Sprite sprite = platforms.get(i).getSprite();
            sprite.setPosition(body.getPosition().x - sprite.getWidth()/2, body.getPosition().y - sprite.getHeight()/2);
            sprite.setRotation(body.getAngle() * MathUtils.radiansToDegrees);
            sprite.draw(batch);
        }
}

public void renderPlayer(){
    world.getBodies(tmpBodies);
    for(Body body : tmpBodies)
        if(body.getUserData() != null && body.getUserData() instanceof Player){
            Player player = (Player) body.getUserData();
            Sprite sprite = player.getSprite();
            sprite.setPosition(body.getPosition().x - sprite.getWidth()/2, body.getPosition().y - sprite.getHeight()/2);
            //sprite.setRotation(body.getAngle() * MathUtils.radiansToDegrees);
            sprite.draw(batch);
            if(player.isPlayEffect()){
                Assets.sparks.setPosition(body.getPosition().x , body.getPosition().y - sprite.getHeight()/2);
                Assets.sparks.setDuration(200);
                Assets.sparks.start();
            }

        }
}

public void renderBackground(){
    world.getBodies(tmpBodies);
    for(Body body : tmpBodies)
        if(body.getUserData() != null && body.getUserData() instanceof Background){
            Background background = (Background) body.getUserData();
            Sprite sprite = background.getSprite();
            //sprite.setPosition(body.getPosition().x - sprite.getWidth()/2, body.getPosition().y - sprite.getHeight()/2);
            sprite.setBounds(bottomLeft.x, camera.position.y - camera.viewportHeight /2, camera.viewportWidth, camera.viewportHeight);
            sprite.draw(batch);
        }

}
private void doPhysicsStep(float deltaTime) {
    // fixed time step
    // max frame time to avoid spiral of death (on slow devices)
    float frameTime = Math.min(deltaTime, 0.05f);
    accumulator += frameTime;
    while (accumulator >= TIMESTEP) {
        world.step(TIMESTEP, VELOCITYITERATIONS, POSITIONITERATIONS);
        accumulator -= TIMESTEP;
    }
}

and player update:

public void update(float delta) {
    stateTime += delta;
    if(state==JUMP){
        sprite.setRegion(jump.getKeyFrame(stateTime));
        if(jump.isAnimationFinished(stateTime)){
            state = IDLE;
            stateTime = 0;
        }
    }else{
        sprite.setRegion(idle.getKeyFrame(stateTime));
    }
    if(Gdx.app.getType() == ApplicationType.Android )
        velocity.x = -Gdx.input.getAccelerometerX() * (movementForce / 10f);
    if(applyJump){
    body.applyLinearImpulse(0, jumpPower, body.getWorldCenter().x, body.getWorldCenter().y, true);
    applyJump = false;}
    body.setLinearVelocity(velocity.x, body.getLinearVelocity().y);
}

where applyJump variable is setted at contact in postSolve() method.

Thanks in advance

Upvotes: 0

Views: 1518

Answers (1)

SpacePrez
SpacePrez

Reputation: 1086

Well, that's two different problems then, right? It isn't smooth, and its drawing multiple sprites when it shouldn't be?

Lets tackle the second one first, that should be pretty obvious. Either you're making multiple calls to render the sprite somewhere, or you're not clearing the frame properly. It looks like you're clearing it, so you've gotta go through all your render code and see how you're drawing that texture twice. Somewhere its happening.

world.getBodies(tmpBodies);
    for(Body body : tmpBodies)

Why does this code exist? Does the player character have multiple sprites? I wouldn't handle it this way; does the number change over time? Are there new players being created? You should probably create a separate Player class and allow it to manage its own state and data. Use OOP principles! Too much here is being done by a single GOD class, very procedural style. Bad Java.

If left/right movement isn't smooth you need to work on your physics.

Upvotes: 1

Related Questions