Game Loop question: Which way is better?

So, I have been doing a little Java Game programming for fun and I have seen two maybe three ways to do the game loop. I was just wondering if one is better then the other and why. So the first way and the way I currently do it is using javax.swing.Timer and a custom action listener. The second way I have seen is just a Thread using System.getTimeMillis() to get the timing, and the final one is the same as the second but using sleep() instead of System.getTimeMillis().

It depends a lot on what type of game you are doing

  1. javax.swing.Timer - for lightweight games where the timer routine is very quick also if you want to use a swing gui and not have to worry about threading issues.
  2. Fixed sleep time, measure game time with System.nanoTime() - the best option for smooth animation, don’t use currentTimeMillis() it is way less granular on some platforms.
  3. Fixed time step with a sleep for remainder - sleep generally has pretty low granularity worse for smooth animation but a fixed timestep can have quite a few advantages (stable/repeatable).

If you use a fixed sleep time (option 2), you may need to worry about interpolation as the execution time for each step may be different. For a simple game, I would go with fix time-step (option 3).

If the JGO Wiki ever reappears, this would be a good topic to get nailed down once and for all.

do you have any templates for option 2 and 3?

I wrote a tutorial on game loops on my website. Here’s the source code if that’s all your interested in. I need to do a little bit of fix up (I shouldn’t have used doubles to represent the time in seconds), but it should work.


public abstract class GameLoop
{
    private boolean runFlag = false;
 
    /**
     * Begin the game loop
     * @param delta time between logic updates (in seconds)
     */
    public void run(double delta)
    {
        runFlag = true;
 
        startup();
        // convert the time to seconds
        double nextTime = (double)System.nanoTime() / 1000000000.0;
        double maxTimeDiff = 0.5;
        int skippedFrames = 1;
        int maxSkippedFrames = 5;
        while(runFlag)
        {
            // convert the time to seconds
            double currTime = (double)System.nanoTime() / 1000000000.0;
            if((currTime - nextTime) > maxTimeDiff) nextTime = currTime;
            if(currTime >= nextTime)
            {
                // assign the time for the next update
                nextTime += delta;
                update();
                if((currTime < nextTime) || (skippedFrames > maxSkippedFrames))
                {
                    draw();
                    skippedFrames = 1;
                }
                else
                {
                    skippedFrames++;
                }
            }
            else
            {
                // calculate the time to sleep
                int sleepTime = (int)(1000.0 * (nextTime - currTime));
                // sanity check
                if(sleepTime > 0)
                {
                    // sleep until the next update
                    try
                    {
                        Thread.sleep(sleepTime);
                    }
                    catch(InterruptedException e)
                    {
                        // do nothing
                    }
                }
            }
        }
        shutdown();
    }
 
    public void stop()
    {
        runFlag = false;
    }
 
    public abstract void startup();
    public abstract void shutdown();
    public abstract void update();
    public abstract void draw();
}

Andrew Davison covers this in his book “killer game programming”, You can download the source he has for various timers here http://fivedots.coe.psu.ac.th/~ad/jg/ch1/index.html

I had some weird problems using the game loop code from that book, though I admit that I did make a couple of small changes to it. The problems were only a significant issue on older computers, so it took me years to figure out what caused it. I deleted the portion of my game loop that was from Killer Game Programming in Java, and my code suddenly started working.

I use that loop now, with some changes. I’m curious what your game loop looks like now. Can you share it?

protected final void runSafely() {
	//verify that the loop will continue
	shouldContinueLoop = true;
	
	//This variable is used for computing the length of an update phase.
	long lastUpdatePhase = Time.currentTimeMillis();

	while(shouldContinueLoop) {
		//if the application isn't active, sleep for half a second
		if(!isApplicationActive()) {
			try {
				Thread.sleep(500);
			} catch(InterruptedException exception) {}
				
			continue;
		} //end if the frame isn't active
		
		//figure out the start of the current phase
		long currentCycle = Time.currentTimeMillis();
		long updatePhaseLength = currentCycle - lastUpdatePhase;
		if(updatePhaseLength > maximumUpdateLength)
			updatePhaseLength = maximumUpdateLength;
		
		//update the current model
		doUpdatePhase(updatePhaseLength);
		lastUpdatePhase = currentCycle;
	
		//render the game
		render();
		
		//yield to other threads
		Thread.yield();
	} //end while forever
} //end runSafely

I was just talking about this at http://www.java-gaming.org/index.php/topic,23831.msg198753.html#msg198753. I added the Thread.yield because of what they said, though it doesn’t seem to change anything. My current code doesn’t have any of the sleeping and oversleeping stuff from Killer Game Programming in Java.

I haven’t had any trouble with the Killer Game loop, but I haven’t run it on an older computer. I will have to look at this more.

In all fairness, I did screw around with the Killer Game loop slightly. It’s supposed to have an update phase that always uses a constant time period, but I made mine use a variable time period. I was losing time when the timer was too granular because it would still sleep or yield or whatever.