Well, obviously, I designed my code to be able to handle a delay every once in a while, but when the timer is consistently late by a massive margin (in computer terms) it makes it difficult to write reliable code.
Instead of drawing a frame every 20ms and sleeping to aviod wasting cpu time, you have max out the cpu drawing frames one after another, additionally having to **guess** how long they took to draw!
Right now I've created a class that uses System.nanoTimer to measure time elapsed in milliseconds like so..
// it would probably be proper Java technique to make elapsed_ms private, and use a method
// to fetch it's value, but remember this is supposed to be a high resolution timer, which means
// it should run as fast as humanly possible, which means letting outside classes access this
// field on their own.
class HighResTimer
{
private long n1;
private long n2;
public long elapsed_ms;
public HighResTimer()
{
n1 = 0;
n2 = 0;
elapsed_ms = 0;
}
public void start()
{
n1 = System.nanoTime();
}
public void stop()
{
n2 = System.nanoTime();
elapsed_ms = ((n2 - n1) / 1000000L);
}
// this is the exception to my rule, so you can see how much time has gone by without stopping it..
public long getElapsed()
{
n2 = System.nanoTime();
return ((n2 - n1) / 1000000L);
}
}
In my primary loop I have the following..
// this gives me the precise number of milliseconds of work+sleep that will give me roughly
// 30 frames per second.
long required_ms = 1000 / 30;
// two timers so I can measure how long it took for one render pass, and how long we actually
// slept afterwards.
HighResTimer renderTimer = new HighResTimer();
HighResTimer sleepTimer = new HighResTimer();
// the loop
while(true)
{
// measure how long it took to render once...
renderTimer.start();
renderManager.renderScreenStuff();
renderTimer.stop();
// renderTimer.elapsed_ms now tells us how long it took
// measure how long we slept (I left out the try/catch for clearity)
sleepTimer.start();
Thread.sleep(required_ms - renderTimer.elapsed_ms);
sleepTimer.stop();
}
Now I don't have sleepTimer being used here because I haven't gotten that far yet since I've been spending most of my time on the renderer. Even without measuring the exact time the sleep actually took, this still keeps my engine within 2 FPS of the target 30. If you add another long above the while() loop that stores the previous passes sleep time, you can subtract that from the next sleep to compensate for it taking longer than expected. My engine has a thread for playing music and when you Thread.sleep() your main thread on purpose, it's going to lose context to the music thread and there's really no telling just how long it will run. It might take 30ms because there's a lot of disk access going on and it had to wait to read the next bit of music, or some such.
Additionally, I don't use Thread.sleep() inside the main loop, I use Util.sleep (Util being my own abstract class) that just wraps a Thread.sleep() with a few extras, such as detecting the possibility that the math I have above could quite possibly ask Thread.sleep() to sleep for 0ms, or even a negative time causing an except FPS, I don't really need to do this.
Hope this helps.