Thread or Timer ?

Hi !
I am creating my first Game in Java and i have a question about the main-loop.
Here in the forums I see a lot of stuff like this:

while (running) {
paint();

timer.sleepUntil(lastFrameStart+frameTime);
}

Why don’t you use a Timer-Thread like this:
tm = new javax.swing.Timer(41, maingame) ?

I tested both here and with the Thread I have an Cpu-Usage of 5% but with the while-sleep I have 100% Cpu-Usage.

Troggan

If you are seeing such a difference you are doing something wrong. I don’t think timer.sleepUntil() is the method most people are using (I didn’t even know that was an available API to tell the truth). I have only seen direct calls to Thread.sleep() with the interval calculated appropriately.

Depending on your game requirements the timer method may not be suitable. Most action games use “active rendering” (wish I had a link to the Wiki definition of active rendering). So they don’t respond to requests to paint via the AWT message thread. They draw when they decide it is time to draw and force drawing to the screen/window directly. If you can get away with “passive rendering” then a Timer might be more suitable. You could animate based on your timer and call repaint() when you have updated your game state. When I was first learning the Java APIs that is what I did and I was basically successful, but I would use active rendering if I was to do the same project today. Passive rendering is better if you don’t have a lot of fast action. I would probably do board games, card games, and turn based strategy games with passive rendering. Anything like what you see in an arcade, from pac man to a super 3D shooter would work best with active rendering. Pac man and other games at that level can be done with Java 2D, anything more and it is probably better to look into the OpenGL bindings, even for 2D (e.g. Alien Flux).

timer.sleepuntil() is not in the API… most java-games I see have something like this. They normaly use a dll to get the Windows High Resolution Timer (e.g. Warlock2d) and use it to set their frame rate. If I don’t wait at the end of painting a frame, my Game will have over 80 Frames/sec and all Sprites are moving too fast.

Warlock2d and the other Games I saw try to wait after painting the Scene. They wait till a certain amount of time has gone by.With that they force the game to run with a fix framerate.

But why do they try this with a waiting-loop? Isn’t it nicer to get a fixed Frame rate with that TimerThread I mentioned? The TimerThread calls the GameScreen Class every 1/30 sec and the GameScreen Class repaints the Screen.

It costs less CPU power. In fact I changed the Warlock2d game to use a TimerThread instead of the Waiting-Loop.
That’s where I got the numbers from!

Ok… either way will work, but the timer version is a bit more complex when the game is typically a single loop. You are still doing the same loop with the timer method, but you have made it a tiny bit harder to see that it is still just a basic single threaded loop. For 30fps it will work fine I guess… but what if you are wanting smoother animation at 60fps… is the frame update still steady? It really doesn’t matter if your game is working as well as you want it to. (Did you test on multiple platforms?)

The single loop with a sleep method had the advantage that it fits better with a full screen game based on a page-flipping buffer strategy. If your page flipping is synchronized to the vertical refresh then you have a built-in ‘sleep’ with exactly the right delay as it waits for the refresh, and you get the smoothest animation, if you are updating animations with every display refresh. You will still need an accurate measurement of how fast the pages are flipping so you can advance your animations by the appropriate amount - so a hi res timer is still helpful.

I still say that 5% to 100% CPU clearly indicates that the 100% CPU method has a design flaw. Dig deeper (profile the code) to find out why that is happening. Once you fix the problems with that version, profile both versions and compare, take measurements to see how steady the framerate is.

I tested it on 3 machines (p3 500mhz, 733mhz and athlon 2500+) and everywhere it has that “problem”. I profiled the code and saw the problem, why it uses 100% of the CPU.

It’s the waiting itself that uses the CPU Power.
The waiting function looks like this:

public void sleepUntil(long ticks) {
while(getClockTicks() < ticks) Thread.yield();
}

And because of nothing else running on my machine, the game gets all the power there is available. if i start using other applications in the background, they got the cpu time they need.

I do believe that you’re referring to GAGETimer. sleepUntil() works by using Thread.yield() to give time to other threads/programs while still using anything that noone else wants. This is not a problem! It is a feature. You see, using thread sleeping can result in your application having inaccurate timing. Inaccurate timing leads to animation that is less than smooth.

Fortunately, this is only necessary for non-vsynced games. VSyncing blocks the thread until the monitor refreshes. So what’s the downside? VSyncing is currently only available on Windows in full-screen exclusive mode. All other cases need some sort of frame limiting method. You will need to choose the method that works best for you and your game.

EDIT: BTW, your timer thread method is not only highly inaccurate, it’s likely to not be able to generate 60+ fps on most machines. It may work for 30 fps, but given the Windows 10-50ms resolution for System.currentTimeMillis(), I doubt it. (10ms allows you to time 100fps, but in a very inaccurate fashion. 50ms for the 9x OSes can’t even do 20fps. Look for the “New Timer Algorithm” thread for more info.)

I tested a lot of things today with various configurations (cpu, os etc…) and i come to the decision to use the sun.misc.perf-timer in combination with Thread.yield().
But I will add a switch to be able to use the Thread.sleep() mechanism. perhaps i call it normal and high mode :wink:

Why? Because if I show the game to other people they will see the cpu usage and say that java is so slow that it can’t even show the little game i am coding without using all the cpu power that is available.

I generally use system time to keep a steady ‘loop rate’ (game speed) and then have the repaint method called after the main loop, but only if the main loop is keeping up to speed.

eg.
I generally have gameSpeed set to 30 (30 loops a second).
If the system is running to slow, it’s set up to skip rendering to keep the loop rate constant (so if the game runs badly, all characters etc move at the same speed).

This is achieved by performing the main loop if the time through the current second (the millisecond) is up to the current loop time, which is incremented by 1000 / gameSpeed per loop.

It then checks if the loop rate is keeping up by checking if there have been enough loops this second according to the current millisecond. If there has, rendering takes place.

This also allows the frame rate and loop rate to be easily recorded, by having a fpsCounter that is incremented for each repaint call, and a lpsCounter incremented per loop.

Then just display them at the end of each second.

One thing that does confuse me is programs returning frame rates to decimal points - did it only half finish the rendering for the final frame?

The problem with system time (as Jbanes, troggan and others) have pointed out in the past, is that on windows the resolution of the times can be as bad as ~50ms. This means that at times your fps will be 20.

This has come up time and time again with GAGE (maybe add a FAQ somewhere?). If someone says to you that java is slow because it uses up 100% when nothing else needs any time tell them that to comment on the speed of program they should really understand what is going on first.

The misc-timer you’re using isn’t supported yet, e.g. its not public, so you’re setting yourself up for a fall when SUN decide to change its location, or someone trys to run your game on 1.3 or something… stick to GAGE for now, maybe the SUN guys will sort the time out in 1.5. At which point I think they’ll be a whole bunch of people that swap over (no offence JBanes :))

Kev

2 ways of calculating the FPS are :-

  1. 1000/ Time taken to render 1 frame

  2. Take the average fps over several seconds.

Either of those can lead to fractional fps.