Run code for Java 1.1 constant FPS?

Hi all, can someone post the accepted code for keeping a constant frame rate in Java 1.1, knowing that it has a lot of timing problems in Windows. I’ve been looking around with no luck. I just need the source to keep a constant 30 FPS, even if its not perfect. This is what I have now, from my research on the web, but its not working out right. It uses yield() to delay. I’ve seen many variantions, but I need it only for Java 1.1 and it has to be a constant rate. I won’t be showing more or removing more frames depending how many were missed etc.
`
public void run() {
long start_timer=0;
long fps_ms=1000/30; //30 FPS

while(thread!=null) {
start_time=System.currentTimeMillis();

  //DO STUFF HERE

  start_timer+=fps_ms;
  long delay_start=System.currentTimeMillis();
  long delay_ms=Math.max(0,start_timer-delay_start);
  while(System.currentTimeMillis()-delay_start < delay_ms) { 
     try{thread.yield();} 
     catch(Exception e) {}
  }

}
`
Thanks!

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

I’m trying to get a Java 1.1 applet game working. I see other people do it, is it just by guessing the frame rate delay? Even if it was 1.4, I don’t think I can use GageTimer at all with applets. I only know about 1.5 applets being able to use the proper nano timer. Is that true?

[quote]I’m trying to get a Java 1.1 applet game working. I see other people do it, is it just by guessing the frame rate delay?
[/quote]
No, they don’t guess. They calculate how much clock ticks drawing one frame should take, if it took less, sleep for the remaining amount of clock ticks. How accurate this is depends on the resolution of the used timer.

[quote]Even if it was 1.4, I don’t think I can use GageTimer at all with applets. I only know about 1.5 applets being able to use the proper nano timer. Is that true?
[/quote]
gageTimer works on from 1.1 up to 1.5, it delivers a higher precision on certain platforms. Like nanotimer on 1.5. You won’t need to bother with this as you can use the generic loop i described above and let gagetimer handle the timer implementation.

You could extend gagetimer a bit with the alternative timers i described above to support more hirestimers available.