I'd like to run a function 60 times a second. I prefer to use Util timers which I see a very simple method
int second = 1000;
int fpsLimit = 60;
Timer timer = new Timer();
TimerTask task = new TimerTask(){
public void run(){
//
}
}
timer.scheduleAtFixedRate(task, 0, second / fpsLimit);`
but I see a lot of people use game loops, which are much longer and more complex.
long lastime = System.nanoTime();
double AmountOfTicks = 30;
double ns = 1000000000 / AmountOfTicks;
double delta = 0;
int frames = 0;
double time = System.currentTimeMillis();
while(isRunning == true) {
long now = System.nanoTime();
delta = (now - lastime) / ns;
lastime = now;
if(delta >= 1) {
Update();
Render();
frames ;
delta--;
if(System.currentTimeMillis() - time >= 1000) {
System.out.println("fps:" frames);
time = 1000;
frames = 0;
}
}
}
and sorry, since I don't really understand gameloops, are there any advantages of using them other than tracking the fps?
CodePudding user response:
The answer can probably be summarized in a single word: accuracy.
Timers often use Thread.sleep or another comparable method that puts one thread to sleep and then wake it up when the time is elapsed.
It works, but the resolution is usually not better than a few dozens milliseconds. Equally, we can say that the delay is rounded upwards, or the thread may sleep slightly longer than what has been specified, or the timer may not wait exactly the same time between two calls. This means basically the same thing.
Of course for running a game and rendering it properly, it's far too inaccurate. Counting yourself precisely how much you need to wait and specifying a target delay in nanoseconds is required.
CodePudding user response:
A game loop might run as fast as it can, or it might have a rate limit. Your example seems to be rate-limited, but it's a busy wait loop. It recalculates delta
as fast as it can, and then calls Update
and Render
when delta
reaches a certain value. This is inefficient.
Timer
is a little bit like your game loop, but more sophisticated. Take a look at the source, particularly the TimerThread
class and its mainLoop
method. The thread waits on the task queue until the time of the next scheduled task. When a task is inserted, the thread wakes up, performs any tasks that are due, and then waits again until the next task is due.
Game loops are introduced as a concept in many books and tutorials, but there's little or no reason to ever write one yourself. In practice, the main loop is often provided for you by whatever UI or game engine framework you're using. If not, something like Timer
may work just fine and save you the trouble of writing it yourself.