1

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?

  • 2
    First of all, you should use `javax.swing.Timer`, not `java.util.Timer`. – Holger Mar 17 '22 at 15:31
  • 2
    You are supposed to do real research before posting questions here. Just putting "game loop" into the search field gives you some ideas, like: https://stackoverflow.com/questions/2565677/why-is-a-main-game-loop-necessary-for-developing-a-game – GhostCat Mar 17 '22 at 15:33
  • 1
    Thank you, I actually did a research. I still didn't get why I should write long code when util timers can do the job for you. – Michel Beṭar Mar 17 '22 at 15:36
  • @Holger Only if it's a Swing app. – Tech Inquisitor Mar 17 '22 at 15:37
  • 1
    @TechInquisitor the question said Swing before the edit. Besides that, I don’t know of any UI framework without a thread confinement policy, in other words, `java.util.Timer` is always wrong, regardless of the framework. – Holger Mar 17 '22 at 15:39
  • 3
    As a side note, the game loop code is horrible, mixing up `System.currentTimeMillis()` and `System.nanoTime()`, using `double` for the calculation, etc. – Holger Mar 17 '22 at 15:46
  • This isn't my game loop at all. – Michel Beṭar Mar 17 '22 at 15:46
  • 1
    The key part of the game loop is the separation of updating the game model and rendering the game images. The rest of the code attempts to smooth out the frames per second. A Swing Timer set for 40 milliseconds (25 frames / second) will not always fire after exactly 40 milliseconds, so you adjust the delay to try and smooth out the frame rate, – Gilbert Le Blanc Mar 17 '22 at 15:47
  • 2
    An alternative view: game loops are useful if you don't mind using up 100% CPU time of one processor core, don't understand the concept of threads and can't be bothered to learn it. (But the other comments/answers referring to accuracy make a better point.) – k314159 Mar 17 '22 at 15:49
  • 1
    Be careful with statements like `while(isRunning == true) {` as it may never wake up even if `isRunning` is set to false elsewhere (it depends on how your code is written and if you are using threads) – WJS Mar 17 '22 at 19:06
  • @TechInquisitor *Only if it's a Swing app.* Well, using it is self-fulfilling since it now becomes a Swing app. I prefer it since it's easier to use in most cases. – WJS Mar 17 '22 at 19:11

2 Answers2

1

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.

QuentinC
  • 12,311
  • 4
  • 24
  • 37
1

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.

Tech Inquisitor
  • 343
  • 1
  • 7
  • A separate game loop makes sense if you move objects at a speed that overturns collision detection. If you move an object with 300 pixels per second and have obstacles that are less than 5 pixels thick, at 60 updates per second it will happen more often that collisions are not detected. Therefore updates (calculation of position etc.) as many as possible, draws (drawing of the objects) as many as necessary! –  Mar 17 '22 at 16:37
  • @QuinncyJones Also consider [Continuous Collision Detection](https://digitalrune.github.io/DigitalRune-Documentation/html/138fc8fe-c536-40e0-af6b-0fb7e8eb9623.htm). – Tech Inquisitor Mar 17 '22 at 16:43