rework the main loop to use a different method for fixed timestep

Use Glenn Fiedler's "Fix your timestep!" article's approach instead.
Just need to remember to always interpolate between prevState and
currentState and not extrapolate from the currentState when rendering
(for best results!)
This commit is contained in:
Gered 2013-12-30 14:00:14 -05:00
parent 8cd834c455
commit 8d9457b872
2 changed files with 15 additions and 15 deletions

View file

@ -1,7 +1,7 @@
package ca.blarg.gdx; package ca.blarg.gdx;
public interface GameLooper { public interface GameLooper {
void setTiming(int updatesPerSecond, int maxFrameSkip); void setTiming(int updatesPerSecond, float maxFrameTimeSeconds);
int getUpdateFrequency(); int getUpdateFrequency();

View file

@ -2,15 +2,13 @@ package ca.blarg.gdx;
import com.badlogic.gdx.ApplicationListener; import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.utils.TimeUtils;
public class GdxGameAppListener implements ApplicationListener, GameLooper { public class GdxGameAppListener implements ApplicationListener, GameLooper {
int updatesPerSecond; int updatesPerSecond;
int updateFrequency; int updateFrequency;
int maxFrameSkip; float maxFrameTime;
long nextTick = 0; float accumulator;
int loops;
float updateDelta = 0.0f; float updateDelta = 0.0f;
float renderDelta = 0.0f; float renderDelta = 0.0f;
@ -29,7 +27,7 @@ public class GdxGameAppListener implements ApplicationListener, GameLooper {
Services.register(GameLooper.class, this); Services.register(GameLooper.class, this);
setTiming(20, 5); setTiming(20, 0.25f);
try { try {
gameApp = gameAppType.newInstance(); gameApp = gameAppType.newInstance();
@ -46,7 +44,6 @@ public class GdxGameAppListener implements ApplicationListener, GameLooper {
gameApp.onCreate(); gameApp.onCreate();
nextTick = TimeUtils.millis();
} }
@Override @Override
@ -57,15 +54,18 @@ public class GdxGameAppListener implements ApplicationListener, GameLooper {
@Override @Override
public void render() { public void render() {
loops = 0; float frameTime = Gdx.graphics.getRawDeltaTime();
while (TimeUtils.millis() > nextTick && loops < maxFrameSkip) { if (frameTime > maxFrameTime)
gameApp.onUpdate(updateDelta); frameTime = maxFrameTime;
nextTick += updateFrequency; accumulator += frameTime;
++loops;
while (accumulator >= updateDelta) {
gameApp.onUpdate(updateDelta);
accumulator -= updateDelta;
} }
renderDelta = (float)(TimeUtils.millis() + updateFrequency - nextTick) / (float)updateFrequency; renderDelta = accumulator / updateDelta;
gameApp.onRender(renderDelta); gameApp.onRender(renderDelta);
} }
@ -90,11 +90,11 @@ public class GdxGameAppListener implements ApplicationListener, GameLooper {
} }
@Override @Override
public void setTiming(int updatesPerSecond, int maxFrameSkip) { public void setTiming(int updatesPerSecond, float maxFrameTimeSeconds) {
this.updatesPerSecond = updatesPerSecond; this.updatesPerSecond = updatesPerSecond;
updateFrequency = 1000 / this.updatesPerSecond; updateFrequency = 1000 / this.updatesPerSecond;
this.maxFrameSkip = maxFrameSkip;
this.updateDelta = updateFrequency / 1000.0f; this.updateDelta = updateFrequency / 1000.0f;
this.maxFrameTime = maxFrameTimeSeconds;
} }
@Override @Override