Unstable refresh rate

Hi,

I am encountering an awful graphical rendering for a Java-Game and it seems to come from an unreliable refresh rate. I use a classical game loop :

public void loop(long elapsedTime) {
Graphics2D g = (Graphics2D) frame.getBufferStrategy().getDrawGraphics();
stage.update(elapsedTime);
stage.draw(g);
g.dispose();
frame.getBufferStrategy().show();
}

Depending on the ‘stage.update(elapsedTime);’ and ‘stage.draw(g);’ steps, the duration of a loop can vary a lot, and from time to time, it can takes more than 100 ms. This way objects (sprites) on the graphical scene seems more to make discrete jumps from a position to another rather than to follow a continuous path. I think this rendering is non acceptable for a game.

Anyway, I have always seen such behviour of Java apps when they have animations so I am not really optimist. The only solution I see is to try to control the maximal duration of operations in a loop and to try to avoid the unpredictable ones (it don’t seem to be possible at 100%).

So my questions are : do you encounter the same problem ? do you agree with the diagnostic ? do you have a solution ?

Thanks everybody,

Guillaume

How are you calculating the elapsed time? If you’re using System.currentTimeMillis() that may well be your problem. Windows timers can be low res. If so… check out GAGETimer (http://java.dnsalias.com) or nanoTime() in Java 1.5.

Kev

I have tried getting elapsedTime with System.nanoTime() and it gets a bit better, but the refresh rate remains unreliable…

In fact I really wonder if it is possible to a have a constant fps rate (>50), since I have never seen a smooth animation part of a Java app, has anyone ?

Guillaume

[quote]I have tried getting elapsedTime with System.nanoTime() and it gets a bit better, but the refresh rate remains unreliable…
[/quote]
Can we see your timing code?

[quote]In fact I really wonder if it is possible to a have a constant fps rate (>50), since I have never seen a smooth animation part of a Java app, has anyone ?
[/quote]
Most people here use either GAGETimer or the one built into LWJGL. Between those, we have no problems getting a smooth framerate. An FPS counter will usually show some variation in one direction or another, but that’s more because of the inaccuracy of trying to calculate the frame rate.

"Can we see your timing code? "
Here it is:

private void startLoop() {
long startTime = System.nanoTime()/1000000;
long currentTime = startTime;

  while (isRunning) {
        long elapsedTime = System. nanoTime()/1000000 - currentTime;
        loop(elapsedTime);
        currentTime += elapsedTime;
  }

}

I am going to change this 1000000 factor…

So… how does this code stabilize the framerate? It looks like you’ve got an Ok attempt at figuring out the time between, but you need to use it effectively in a sleep() or yield() method if you want to stabilize the frame rate.

For example, with GAGETimer you would do this:

  AdvancedTimer timer = new AdvancedTimer(); 
 long sleepTime = timer.getTicksPerSecond()/60; //60 fps 
 long ticks = 0; 
   
 timer.start(); 
   
 while(true) 
 { 
     //draw stuff 
       
     timer.sleepUntil(ticks+sleepTime); 
     ticks += sleepTime; 
 } 

That code will make sure that each frame renders in is as precise a time slice as possible. The getTicksPerSecond() returns the resolution of the timer, which ranges from worst case of 100 ticks per second, all the way up to the nanosecond range. As long as you compute the slices as you see above, the precision of the timer doesn’t actually matter.

Ok I hadn’t thought about it, thinking looping as fast as possible would be good… So I am going to try it, thanks !

But I still feel there can be problems : in the example you have given, the 'timer.sleepUntil(ticks+sleepTime); ’ can wait to stabilize the framerate, but it can’t rewind time ! If the update(), draw() and show() steps take more than ‘sleepTime’, the framerate will locally fall and the animation will suffer from lag.

What do you think ?

[quote]Ok I hadn’t thought about it, thinking looping as fast as possible would be good… So I am going to try it, thanks !
[/quote]
If you need as fast as possible, then you should just put a “Thread.yield()” at the end of your loop. That will give the rest of the system a bit of breathing time between your frame renders. However, keep in mind that rendering as fast as possible will result in your framerate being all over the map. Anything the system does will be noted in your framerate. That being said, you should still be about to get around 250-500 FPS.

Note that fullscreen, buffer strategy, and VSync combined automatically lock you into the maximum refresh rate of your monitor.

[quote]But I still feel there can be problems : in the example you have given, the 'timer.sleepUntil(ticks+sleepTime); ’ can wait to stabilize the framerate, but it can’t rewind time ! If the update(), draw() and show() steps take more than ‘sleepTime’, the framerate will locally fall and the animation will suffer from lag.
[/quote]
You might want to take another look at the algo. The beauty of it is that if the previous frame lagged, the next one will give up some of its sleep time to cover the difference! Note that it can’t do anything to fix loops that generally fall behind the targeted amount of time.

I don’t know much about VSync, what is it ? :stuck_out_tongue:

Is it automatically enabled in fullscreen mode ?

[quote]I don’t know much about VSync, what is it ? :stuck_out_tongue:

Is it automatically enabled in fullscreen mode ?
[/quote]
Ok, here goes the fifteen second lesson in monitor physics:

CRT monitors function by scanning an electron bean from left to right along each row of pixels. This path results in two periods when the electron beam is turned off: The horizontal sync, and the vertical sync.

The horizontal sync is when the beam moves from the right to the left after tracing a line. This happens thousands of times per second, but doesn’t give much time when the beam is off. Old game consoles used to use that time to setup the next line of graphics (“riding the beam”), but modern hardware uses a framebuffer so that the programmer doesn’t have to worry about it.

The vertical sync is when the beam moves from the bottom of the screen back to the top. This takes several milliseconds, and is a perfect time to update the framebuffer. Updating the framebuffer at other times tends to result in tearing as half a frame is rendered different from the other half. Even worse, is that drawing can sometimes be seen which results in flickering. Since the screen can’t update any more than the VSync rate, games are usually scheduled to do updates only during the VSync.

Since the video signal contains the VSync and HSyncs, this trick works on LCD monitors as well. Any questions?

really great explanation! ;D I think that you should write an article or something like that about timers and all the stuff around it. It seems to be a question that appears all the time. I myself had questions about it.