LibGDX使用ashley进行插值的固定时间步长游戏循环

时间:2017-10-30 19:55:14

标签: libgdx interpolation game-loop

我有一个问题,因为如果我理解正确的话,我并不是100%确定。我的问题是关于固定时间步长游戏循环与插值

我制作了一个小型测试程序,它似乎有效,但我不确定它是否正确(请参阅下面的代码段)。

我在y轴上以速度1000创建了两个彼此相邻的实体,我可以看到一个清晰的"口吃"使用非插值实体,而插值实体移动非常平滑。

我的问题是我的插值是否正确。我每帧保存实体的先前位置,并将其插入实际当前位置。这是正确的还是插值对未来的下一个位置是否有效?

我希望你明白我的意思:)。

感谢您的帮助!

此致 西蒙

P.S。:还有Family.all(...)的警告很烦人,我不得不使用我个人不喜欢的抑制警告。有没有正确的方法在没有警告的情况下调用它? 编辑:解决了 - 原因是我有源兼容Java 1.6。我现在把它设置为Java 1.8并且警告确实消失了(我认为这已经用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();
}

1 个答案:

答案 0 :(得分:0)

感谢@ Tenfour04的详细信息。我做了一些最后的调整,对我来说现在看起来很顺利。我改变的事情: - 覆盖Game实例的render方法以使用 getRawDeltaTime 而不是getDeltaTime,因为getDeltaTime平均帧之间的时间而不是使用原始值 - 而不是通过物理步骤钳制delta,我现在使用0.25。没有特殊原因,但似乎很多人都在使用这个价值 - 而不是使用lerp进行插值我现在使用插值方法,插值更平滑

改变这三件事(并将物理步骤改为60fps)后,对我来说似乎非常顺利。