Timing in Windows NT has an accuracy of ~15ms, Windows 98 ~50ms I think, you can find out what accuracy the timer has by checking the difference between two measures:
long time = System.currentTimeMillis();
long prev = time;
while (time == prev_time) time = System.currentTimeMillis();
resolution = time - prev_time;
Further, you’d be best off by using GageTimer, it does this for you and better, it detects if there are more sophisticated timers available than System.currentTimeMillis() like the nanotimer or a nativetimer.
It’s an abstraction over the actual implementation of your timing, and you should think in clockticks elapsed instead of time elapsed. The average gameloop would look like this to cap your fps at maxFPS:
timer.start();
startTime = timer.getClockTicks();
ticksPerFrame = timer.getTicksPerSecond() / maxFPS;
while (Thread.currentThread() == thisThread && gameRunning)
{
// measure start of frame
fpsTimer = timer.getClockTicks();
// do your gamelogic here
// blit to screen
// another frame bites the dust
frameCount++;
sleepTimer = timer.getClockTicks();
fpsTimer = sleepTimer - fpsTimer;
// give other threads time to breath
Thread.yield();
// if we limit our fps, sleep the spare nr of clockticks we got left
if (maxFPS > 0) {
if (fpsTimer < ticksPerFrame) timer.sleep(ticksPerFrame - fpsTimer);
}
// measure the amount of ticks it took to paint the frame and sleep (if we cap our fps)
ticksElapsed += fpsTimer + (timer.getClockTicks() - sleepTimer);
// calculate fps related stuff once every x clockticks (as defined in fpsMeasureResolution
if (ticksElapsed >= fpsMeasureResolution)
{
lastFPS = fps;
fps = (int)((frameCount / (ticksElapsed / fpsMeasureResolution))*fpsMultiplier);
frameCount = 0;
ticksElapsed = 0;
}
}
You mentioned you’re using 1.1 (I suppose the MS one, as its the most distributed one) you could also extend the gage library with a hires timer for the msjvm, import com.ms.win32.* and use the Kernel32.QueryPerformanceFrequency(long resolution[]) to query for its resolution. Use Kernel32.QueryPerformanceCounter(long ticks[]) to determine the elapsed clock ticks. I don’t know for sure if untrusted applications (like unsigned applets) are allowed to access it though.
And… to really maximize your compatibility, implement the perf timer for 1.4 jvms (when the nanotimer or native timer are not available)
So extend the timer factory from gageTimer that falls back to less optimal implementations when not available, in this order:
-nanotimer
-nativetimer
-perftimer
-win32 (kernel) timer
-currTimeMillis
Good luck!
Thijs