1
votes

I have come across an issue that I can't seem to fix by myself.

I have implemented this fixed timestep in my render() method like this:

double time = TimeUtils.millis();

    loops = 0;
    while (time > nextGameTick && loops< MAX_FRAMESKIP) {
        gameLogic(1f / gameSpeed);
        nextGameTick += SKIP_TICKS;
        loops++;
    }

    if(!rendererDisposed) {
        interpolation = (time + SKIP_TICKS - nextGameTick)/(SKIP_TICKS);
        camera.update();
        renderer.render(interpolation);
        hud.draw(dt);
    }

The above code is the last implementation from this Link: http://www.koonsolo.com/news/dewitters-gameloop/

And my renderer class draws a batch like this:

batch.draw(assets.getAnimation(),
                player.getInterPos(interpolation).x,
                player.getInterPos(interpolation).y,
                player.getWidth() / 2,
                player.getHeight() / 2,
                player.getWidth(),
                player.getHeight(), 1, 1,
                player.getPolygon().getRotation());

And getInterPos()

public Vector2 getInterPos(float delta){
    interPosition.x = position.x *delta + previousPosition.x*(1-delta);
    interPosition.y = position.y*delta + previousPosition.y*(1-delta);
    return interPosition;
}

What is to be expected: interpolation returns a float value from 0 to 1 that is being used to interpolate between the previous and current positions.

Right now I have TICKS_PER_SEC = 25. Having an FPS: 25 means that renderer and gamelogic gets called 1 time each every frame. This WORKS.

Problem starts when fps!=TICKS_PER_SEC. Having for example 50 fps we would assume that gamelogic will be called once and renderer will be called twice. interpolation now is 0.5 and 1 on the 1st and 2nd renderer call.This WORKS as well. However the drawed sprite starts to behave strange and jumps up and down.

Here is a video that shows the sprites behavior: https://www.youtube.com/watch?v=CE6cQr9o0kA

Now the biggest mystery is that if we add these lines in the renderer class

Gdx.app.log("player has y:"+player.getY()," and previous y:"+player.getPreviousPosition().y);
Gdx.app.log("interpolation: "+interpolation," position: +player.getInterPos(interpolation));
        batch.draw(assets.getAnimation(), ... same as earlier

player has y:23.62517: and previous y:23.09717 interpolation: 1.0: position: (4.5,23.62517) player has y:24.145168: and previous y:23.62517 interpolation: 0.5: position: (4.5,23.88517) player has y:24.145168: and previous y:23.62517 interpolation: 1.0: position: (4.5,24.145168) player has y:24.657167: and previous y:24.145168 interpolation: 0.5: position: (4.5,24.401169)

currentPosition and previousPosition get correctly updated and so does the interpolatedPosition. As you can see the the position is always ascending and in an almost linear manner. So the question is why on earth does the batch render the sprite in 2 different positions and alternates between them?

My gravity function:

//dt is gameSpeed not the deltaTime
velocity.add(acceleration.x*dt,acceleration.y*dt);
position.add(velocity.x*dt,velocity.y*dt);
    if (velocity.y<=-10)
        velocity.y=-10;

When I press the screen this happens:

velocity.set(0,20);

Extra Info:

  • As the object slows down the problems goes away
  • Same thing happens when the objects freefalls down,goes left and right
  • The higher the FPS the more ups and downs it will do
  • replacing getInterPos with getPosition fixes the problem but then the fps = TICKS_PER_SEC

I really hope I was as thorough as possible. This things has been driving me nuts for the past 2 weeks and i just can't seem to be able to fix it.

Any help will be greatly appreciated!

EDIT:

I Have managed to fix the issue. It was due to the fact that I was updating the camera and giving it my players current logic position instead of the interpolated position and updating it inside the game logic function.

So I changed my camera positioning from

camera.position.y = player.getPosition().y;

To

camera.position.y = player.getInterPos(interpolate).y;

And no more artifacts! Leaving it here in case someone comes across a similar problem.

1

1 Answers

0
votes

Not positive this is your only issue.

Since millis() returns a long, time should be a long, not a double:

long time = TimeUtils.millis(); // you declared time to be a double

SKIP_TICKS and nextGameTick must also be longs. And then you need to cast the numerator and denominator to floats before dividing so your interpolation isn't always getting a whole number (0 or 1).

interpolation = (float)(time + SKIP_TICKS - nextGameTick)/(float)SKIP_TICKS;