Search code examples
libgdxinterpolationgame-loop

LibGDX Fixed timestep gameloop with interpolation using ashley


I have a question because I am not 100% sure if I understood it correctly. My question is regarding a fixed timestep game loop with interpolation.

I made a small test program and it seems to work but I am not sure if it is correct (see code snippets below).

I created two entities next to each other on the y-axis with a speed of 1000 and I can see a clear "stuttering" with the non-interpolated entity while the interpolated one moves very smoothly.

My question is if my interpolation is correct though. I am saving the previous position of the entity each frame and interpolate it towards the real current position. Is this correct or should the interpolation work against the future next position?

I hope you understand what I mean :)

Thanks for your help!

Regards Simon

P.S.: Also the warning with Family.all(...) is annoying and I have to use suppresswarning which i personally do not like. Is there a correct way to call it without warnings? edit: Solved - the reason was I had sourceCompatibility to Java 1.6. I set it now to Java 1.8 and the warnings did go away (I think this was already solved with Java 1.7)

// position component
public class PositionComponent implements Component {
  public Vector2 position       = new Vector2(0, 0);
  public Vector2 previousPosition = new Vector2(0, 0);
}

// speed component
public class SpeedComponent implements Component {
  public Vector2 speed = new Vector2(0, 0);
}

// movement system to update position according to speed
public class MovementSystem extends IteratingSystem {
  private final ComponentMapper<SpeedComponent>    speedMapper;
  private final ComponentMapper<PositionComponent> positionMapper;

  @SuppressWarnings("unchecked")
  public MovementSystem() {
    super(Family.all(PositionComponent.class, SpeedComponent.class).get());
    speedMapper = ComponentMapper.getFor(SpeedComponent.class);
    positionMapper = ComponentMapper.getFor(PositionComponent.class);
  }

  @Override
  protected void processEntity(Entity entity, float deltaTime) {
    final PositionComponent positionComponent = positionMapper.get(entity);
    final SpeedComponent speedComponent = speedMapper.get(entity);

    positionComponent.previousPosition.set(positionComponent.position);
    positionComponent.position.add(speedComponent.speed.x * deltaTime, speedComponent.speed.y * deltaTime);
  }
}

// render method of libgdx screen
// fixedPhysicsStep = 1.0f / 25.0f = 25fps
@Override
public void render(float delta) {
  if (delta > fixedPhysicsStep) {
    delta = fixedPhysicsStep;
  }

  accumulator += delta;
  while (accumulator >= fixedPhysicsStep) {
    world.update(fixedPhysicsStep);
    accumulator -= fixedPhysicsStep;
  }

  renderer.render(accumulator / fixedPhysicsStep);
}

// the renderer render method that renders the first entity 
// with interpolation using lerp and the second entity without interpolation
public void render(float alpha) {
  Gdx.gl.glClearColor(0, 0, 0, 1);
  Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
  batch.begin();
  for (int i = 0; i < entities.size; ++i) {
    final Entity entity = entities.get(i);
    final PositionComponent posComp = positionComponentMapper.get(entity);

    if (i == 0) {
      posComp.previousPosition.lerp(posComp.position, alpha);
      batch.draw(img, posComp.previousPosition.x, posComp.previousPosition.y);
    } else {
      batch.draw(img, posComp.position.x, posComp.position.y);
    }
  }
  batch.end();
}

Solution

  • Thanks @Tenfour04 for the details. I did some final adjustments and for me it looks very smooth now. The things I changed: - Override the render method of the Game instance to use getRawDeltaTime instead of getDeltaTime because getDeltaTime averages the time between frames instead of using the raw value - Instead of clamping delta by the physics step I use now 0.25. No special reason but seems like a lot of people are using this value - Instead of using lerp for the interpolation I am using now the interpolate method with Interpolation smoother

    After changing those three things (and changing the physics step to 60fps) it seems very smooth for me.