The Explonoid MIDlet has a game loop that uses one single thread for both painting and updating the game logic. There is also a separate thread for game sounds, so they do not interfere with the game graphics. The threads have a certain time interval reserved for these tasks, and after they are completed, the threads sleep for the rest of the time. This implementation ensures that the game runs at the same pace on every device regardless of the actual processing speed of the device. Selecting a suitable time interval is crucial, since on really slow devices the game can, of course, still slow down if the time interval is too small.
An alternative (and potentially more straightforward) method of
implementing the game loop would be using the Timer
and TimerTasks
classes instead of threading.
Compared to timers, threads can be fairly complicated to handle (especially
when pausing and invoking them). For more information about using
timers, see sections Example: Creating
a game with Game API and Example: Creating
a game using the Gesture API.
To implement the game loop:
Implement threading
by creating the GameThread
class, which extends the Thread
class:
class GameThread extends Thread { private boolean pause = true; private boolean stop = false; private boolean started = false;
Use the requestStart
, requestPause
, and requestStop
methods to control the thread execution.
public void requestStart() { this.pause = false; if (!started) { this.start(); this.started = true; } else { synchronized (this) { notify(); } } } public void requestPause() { this.pause = true; } public void requestStop() { this.stop = true; }
The run
method updates the game logic and the canvas.
/** * The game loop. This example uses only one thread for updating * game logic and for rendering with constant frequency. */ public void run() { long time = 0; while (!stop) { try { if (pause) { synchronized (this) { wait(); } } else { time = System.currentTimeMillis(); checkKeys(); update(); render(); // Sleep the rest of the time time = INTERVAL - (System.currentTimeMillis() - time); Thread.sleep((time < 0 ? 0 : time)); } } catch (Exception e) { } } } }