Smoothing out Android Game Loop
android, game-loop, java, multithreading
Solution
You've actually done most things correctly for this loop. There are a couple of potential pit falls I can see however
You don't pass the frame time to your update method. This means your update method must assume a certain frame time. This is likely the cause of your jumps. You won't get constant frame rates if you are anywhere near the maximum performance of the machine, you just wont. And this broadly doesn't matter. If you miss a frame your brain fills in the missing frame and it looks fine. What absolutely does matter is a variable object speed. In this case a variable frame rate will cause a variable speed of your objects. Your update method should be:
long previousFrameTime=System.currentTimeMillis();
while (running){
.....
.....
long currentTime=System.currentTimeMillis();
long frameTime=currentTime-previousFrameTime
previousFrameTime=currentTime
gamePanel.update(frameTime/1000.0); //I personally like my frametimes in seconds, hence /1000.0, but thats up to you
.....
.....
}
And all movement within the update should take that `frametime` into account when determining how far to move
To show how this matters, see the following two graphs. One with an assumed frame rate, the other with a measured frame rate. The dots represent actual rendered frames and the lines represent the interpolation thats happening within the viewers brain.
You also hold on to the Canvas lock for a lot longer than nessissary. All the way through your update method and through the sleep as well you have a lock on the canvas. This saps performance. Get the lock just before you start rendering and release it as soon as you have finished
gamePanel.update();
canvas = surfaceHolder.lockCanvas();
gamePanel.draw(canvas);
surfaceHolder.unlockCanvasAndPost(canvas);
Problem
I am using the code below as a game loop for a simple Android game. It works just fine, but every now and then there is a little hiccup in the game. Everything freezes for a second and then jumps forward a bit farther than it should. I did a good amount of reading up on game loops, but I'm still having a little trouble implementing a smooth loop. Would interpolating fix this? How could I go about smoothing out the movement? ``` private final static int MAX_FPS = 30; private final static int MAX_FRAME_SKIPS = 5; private final static int FRAME_PERIOD = 1000 / MAX_FPS; protected Void doInBackground(Void... params) { Log.d("MainTask", "starting game task"); Canvas canvas; long begin; // the time when the cycle began long delta; // the time it took for the cycle to execute int sleep; // ms to sleep if ahead int skipped; // number of frames being skipped sleep = 0; while (running) { canvas = null; try { canvas = surfaceHolder.lockCanvas(); synchronized (surfaceHolder) { begin = System.currentTimeMillis(); skipped = 0; gamePanel.update(); gamePanel.draw(canvas); delta = System.currentTimeMillis() - begin; sleep = (int)(FRAME_PERIOD - delta); if (sleep > 0) { try { Thread.sleep(sleep); } catch(InterruptedException e) {} } while (sleep < 0 && skipped < MAX_FRAME_SKIPS) { gamePanel.update(); sleep += FRAME_PERIOD; skipped++; } } } finally { if (canvas != null) surfaceHolder.unlockCanvasAndPost(canvas); } } Log.d("MainTask", "the task is complete"); return null; } ```