Yet another game loop ><

Hey guys i’m new here.
I have been working on a Block breaker clone for desktop as a project to get me used to the best practices and designs idioms for Java games. I have a first version which worked great on my more powerful laptop but when I went to my Net book I found it stuttered badly.I have seen all your different game loops but with no definitive answer on the best I was wondering if you guys could suggest improvements for my attempt at it :slight_smile:


private void gameLoop() {
      // Regenerate the game objects for a new game
      // ......
      state = State.PLAYING;
   
      // Game loop
      long beginTime, timeTaken, timeLeft;
      while (true) {
         beginTime = System.nanoTime();
         if (state == State.GAMEOVER) break;  // break the loop to finish the current play
         if (state == State.PLAYING) {
            // Update the state and position of all the game objects,
            // detect collisions and provide responses.
            gameUpdate();
         }
         // Refresh the display
         repaint();
         // Delay timer to provide the necessary delay to meet the target rate
         timeTaken = System.nanoTime() - beginTime;
         timeLeft = (UPDATE_PERIOD - timeTaken) / 1000000L;  // in milliseconds
         if (timeLeft < 10) timeLeft = 10;   // set a minimum
         try {
            // Provides the necessary delay and also yields control so that other thread can do work.
            Thread.sleep(timeLeft);
         } catch (InterruptedException ex) { }
      }
   }

As a side question is it better to leave Swing to handle the screen or should I handle that myself?

Thanks guys
AbtractChaos

Thread.sleep is very inaccurate on most hardware/OSs, use this trick to force the OS to use the high precision timer:


new Thread() {
    {
        setDaemon(true);
        start();
    }

    public void run() {
        while(true) {
            try {
                Thread.sleep(Long.MAX_VALUE);
            }
            catch(Exception exc) {}
        }
    }
};

Put this in your main.

Also different computers run at different speeds, so it is best to use a deltaTime when moving your sprites. DeltaTime is the time that last frame took to complete. You then pass this number to your update method. To use this deltaTime value, you divide it by 1e9 (nanoseconds per second) and multiply it by the speed at which you want to move per second.


long lastTime = System.nanoTime();
long frameTime = (long)(FPS/1e9);
while(true) {
    long now = System.nanoTime();
    long deltaTime = now - lastTime;
    lastTime += frameTime;
    
    gameUpdate(deltaTime);
    
    ....
}

public void gameUpdate(deltaTime) {
    speed += accelPerSecond * deltaTime / 1e9;
    
    playerPos.x += (speed * deltaTime / 1e9) * Math.cos(direction);
    playerPos.y += (speed * deltaTime / 1e9) * Math.sin(direction);
}

Setting a minimum of 10 milliseconds is also not good because if the game loop is late and needs to catch up, it will never be able to. Don’t set a minimum at all.

Calling repaint() every frame and letting another thread to draw the screen is called passive rendering. The best way to render is active rendering. This is where you call paint in your game loop.

Thanks ;D, I will give that a go

There are schools of thought that disagree with everything (except the sleep daemon Thread to force high precision timer) you’ve said there :slight_smile:

It depends upon what you are doing as to the best approach.

Well i work with java as a job just not gaming and i found it always a good idea to follow “best practises” to keep the code easy to maintain and test. I guess i am trying to find the best approach to making the game loop and the game in general. When it comes to game programming i am a newbie. I will try to explain what i trying to do here and maybe you nice people could be so kind to help :slight_smile:

I want a general architecture to handle everything about the game from resource management to the famous game loop, ability to set full screen on a game would be a nice option too. I understand there is plenty of libraries that will handle all of this for me but i’m afraid i wont learn which could cause more problems in the future :slight_smile:

There is no ‘best’ game loop, just ones with different trade offs. Fixed steps vs. variable steps, fixed framerate vs. variable framerate, different methods that degrade under high load differently (eg. slowdown vs. dropped frames).

It really depends on exactly what kind of game and conditions you’re aiming at. 2d or 3d? 2d games tend to look bad at variable framerates, but 3d can cope with that much better. Single player or networked? Singleplayer games might prefer to have slowdown if the cpu can’t keep up - that’s obviously bad if you’re running a networked game.

Hmm i see your point this all stems from an issue i have where my paddle on a simple block breaker clone is freezes for a split second yet animation continues even updates continue as the balls carry on moving
(quite annoying since I now cant win :stuck_out_tongue: ). All I can guess is it something im missing when it comes to keyboard inputs.

What is this Thread.sleep business? http://why.how.does.that.give.you.high.precision.timer.com/idontunderstand.html

:stuck_out_tongue: your http link doesn’t work for me ::slight_smile:

I remember this being brought up a number of times before, but I never read the rationale behind it. Could you explain how creating a daemon thread leads to Thread.sleep() being more precise?

It forces the OS (only Windows?) to use high precision timers. If you need an even more precise answer I’m sure one of the gurus can answer it :slight_smile:

Mike

Can’t you just use system.getNanotime?

All I know is that the Windows default timer has a resolution of about 10ms, while Linux and Mac are fine are 1ms. There are many topics on JGO where this has been discussed before.

Even the:

System.nanoTime()

, I thought it was released by Java for the very reason of certain OS’s not having a high enough granularity?

It doesn’t matter, even if your using System.nanoTime() in your game loop, Thread.sleep() still has an low (10ms) timer resolution on Windows. So even if you use System.nanoTime() to sync your game loop to the desired FPS/UPS, calling Thread.sleep() to wait for the left over time could be inaccurate, i.e. sleep for an incorrect amount of time, and therefore throw off your game loop. That’s why the daemon hack is used to force Windows to use a higher resolution.

EDIT: I forgot to mention that, according to the Java 6 API, System.currentTimeMillis()'s granularity is dependent on the OS, and System.nanoTime() will return the value of the OS’s most precise available timer, in nanoseconds.

AFAIK making the thread a daemon isn’t important, it is only to keep it from forcing the program to continue running after all the other threads have finished. I believe the JVM will stop daemon threads after all non-daemon threads have stopped and then terminate the program. As for why the hack works, all I know is that if you keep a thread sleeping indefinitely it somehow helps force Windows to use the higher resolution timer. I don’t know if anybody has ever said anything as to WHY it works.

The timer used is global for the OS. All programs that are running use the same timer, and Java switches the operating system to the better timer when sleep() is called and then switches back again when it ends. It doesn’t seem to work when sleeping for short amounts of time though, since the sleep is shorter than the precision of the standard timer. Having an endlessly sleeping thread in the background costs nothing and forces the high-precision timer all the time, and it doesn’t prevent your game from exiting as it’s daemon. Or so I’ve heard.

@AbstractChaos:

In terms of doing things where the “general architecture” handles as much as is reasonable, IMHO, it is quite acceptable to use a Timer object to run your game loop with passive rendering. (I am imagining ra4king with fingers in his ears singing “la la la” while I say this. ;))

With a Timer, one can set a “TimerTask” to repeat indefinitely at a given interval, which circumvents the need to manage cycle time consistency. Quite a few people here don’t like this method, but I think it is fine for games where you have some slack, aren’t trying to eke the max out of every cpu cycle. Note that there are two different repeating modes, one where TimerTasks go end-on-end (and cycle times can slip), another where the system does its best to keep the starting times absolutely on track.

Basically, one writes a TimerTask that will do the following:

  1. call update() on all updateable objects (which could be in a collection)
  2. call reprint() on the display screen.

The calling code specifies the duration, in milliseconds, between the calls to this TimerTask. Pretty simple!

“Killer Game Programming in Java” analyzes the Timer as an option (not their first choice either) and concludes that the java.util.timer (as opposed to the swing.timer) has decent resolution, pretty comparable to their regular game loop. The inaccuracy due to the OS/system clock issue still pertains, as does the solution already mentioned. The concurrency issues that arise with util.Timer seem quite manageable to me. Again, some folks strongly disagree. I think that learning to code in a thread-safe way is generally a good thing.

Since Java 1.5, a ScheduledThreadPoolExecutor is considered a superior option to a Timer. This is what I plan to do try in place of my Timer-based game loop, when I’m ready to refactor Hexara.

I haven’t dealt with full screen mode, but the Java Tutorials devotes a full section just for demanding graphical applications, which includes info on this. If you haven’t seen it yet, you might want to check it out:
http://docs.oracle.com/javase/tutorial/extra/fullscreen/index.html