I am new to Java game programming, but the more I read the more I'm confused, because I've seen several different approaches to make a game loop: 1. The standard approach, that uses the Timer class (seems to be less precise). 2. The more precise approach that uses System.nanoTime. 3. A simple approach that uses scheduleAtFixedRate.
Which one should generally be preferred and where are the advantages/disadvantages of each approach? Thanks in advance for any info.
Answer
For a basic game loop, you'd run a while loop, within which you'd get the time using nanoTime(), determine how much time has passed since the last frame, then update your gamestate and render.
Using http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/System.html#nanoTime%28%29 , you can poll for the elapsed time. Basically...
public static void main(String [ ] args)
{
long current_frame_time = system.nanoTime();
long last_frame_time = current_frame_time;
while(gameIsRunning)
{
last_frame_time = current_frame_time;
current_frame_time = system.nanoTime();
long timeTaken = current_frame_time - last_frame_time;
//update and render game here
}
}
This basic method can be improved upon, e.g. http://www.koonsolo.com/news/dewitters-gameloop/ and http://gafferongames.com/game-physics/fix-your-timestep/.
Alternatively, you could create a timer and set this timer to run your update and rendering every X milliseconds. But, there are some downsides to constructing a gameloop like that.
According to http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Timer.html: "Corresponding to each Timer object is a single background thread that is used to execute all of the timer's tasks, sequentially. Timer tasks should complete quickly. If a timer task takes excessive time to complete, it "hogs" the timer's task execution thread. This can, in turn, delay the execution of subsequent tasks, which may "bunch up" and execute in rapid succession when (and if) the offending task finally completes."
According to http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Timer.html#scheduleAtFixedRate%28java.util.TimerTask,%20java.util.Date,%20long%29: "In fixed-rate execution, each execution is scheduled relative to the scheduled execution time of the initial execution. If an execution is delayed for any reason (such as garbage collection or other background activity), two or more executions will occur in rapid succession to "catch up." In the long run, the frequency of execution will be exactly the reciprocal of the specified period (assuming the system clock underlying Object.wait(long) is accurate)."
Since you usually don't know ahead of time how long a game loop takes, setting a timer to execute your gameloop every X milliseconds (depending on target frame rate) could lead to a few bunched up frames, which would execute whenever a frame is finished instead of when a frame is scheduled. When that happens... why use a timer in the first place?
Now, don't get me wrong, timer is not a bad class, but it is usually better suited to small tasks which need to be done periodically or at a certain time, e.g. a mail client might want to check for new mail every 5 minutes, or a counter might get decremented every second to display a countdown before the start of a race.
No comments:
Post a Comment