4
\$\begingroup\$

Obviously for a game to work you need a game loop... Normally, my game loop would consist of something like this:

while(running){
    update();
    render();
    Thread.sleep(10);
}

This seemed to work fine at first, but then after I started to make my games a bit more complicated the frame rate of my game dropped by 90% in most cases, sometimes they would hang at around <10fps on a high spec system just by simply rendering a couple of 2D image. So I thought to myself: "Should I try putting the render loop on a different thead?". With that in mind, I made a system similar to this:

new Thread(new Render()).start();
new Thread(new GameLogic()).start();

private class Render implements Runnable{
    public void run(){
       while(running){
          render();
      }
    }

private class GameLogic implements Runnable{
public void run(){
   while(running){
      update();
      Thread.sleep(10);
  }
}
}
}

This then caused the graphics to become out of sync with the game update, which then caused the occasional jitter which got quite annoying, later on, I then discovered a use where there is no wait in the loop itself and everything runs as fast as it can, but then you multiply everything in the gameLogic by a deltaTime variable to ensure the game movement is solid. Basically I want to know which way of implementing a game loop is most efficient and whether or not you should render and do gameLogic on the same loop.

\$\endgroup\$
6
  • 4
    \$\begingroup\$ I think the most efficient way to address your performance issues is to do some profiling and optimize the parts that are proven to be too slow. Spawning threads is a bit extreme. Your multithreaded game loop is extreme. What are you doing with those 2D graphics of yours, that's causing 90% in slowdown? \$\endgroup\$
    – user15805
    Commented Mar 27, 2013 at 16:04
  • 1
    \$\begingroup\$ gafferongames.com/game-physics/fix-your-timestep \$\endgroup\$
    – Tetrad
    Commented Mar 27, 2013 at 16:13
  • \$\begingroup\$ "Most efficient" is going to be hard to get answers based on facts. It depends on the requirements of the game, the focus of the game and the implementation details. \$\endgroup\$
    – House
    Commented Mar 27, 2013 at 16:33
  • \$\begingroup\$ It's literally just a 2D scroller \$\endgroup\$
    – Shaun Wild
    Commented Mar 27, 2013 at 17:17
  • \$\begingroup\$ java-gaming.org/index.php?topic=24220.0 \$\endgroup\$
    – Cypher
    Commented Mar 27, 2013 at 18:44

2 Answers 2

6
\$\begingroup\$

If your renderer is to slow to handle "a couple of 2D images", it won't help to simply take the game loop into another thread.

But I assume that you are facing another problem. For a smooth frame rate you have around 16 milliseconds per frame. According to the code example you posted, your game loop includes a fixed the delay of 10 milliseconds.

Thread.sleep(10);

This line costs you 60% of the time you have each frame. So never stop the whole game thread for a fixed delay. With this error, it might even help to use another thread, but that won't solve the cause but the symptoms in your case.

What you want is maybe vertical sync. This is a technique which limit the frame rate to the refresh rate of the monitor, or to a fraction of it. But this feature requires the delay to be dynamically based on the actual frame duration. What it basically does is to let the thread sleep as long as it needs to take the whole 16 milliseconds. Note that most window managers provide an option for vertical sync. I am not familiar with Java but it should have provide it for you, too.

Using vertical sync, it makes sense limit at least to renderer thread and the window thread, since it doesn't make sense to render more frames than the monitor can show. Although it can make sense to run physics simulation in another thread to not slow it down. Despite that, multiple threads in game development are used mainly for the reason of making use of multi core processors. But accessing only one of your cores isn't a bottleneck if you are just working with a couple of sprites.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ this is pretty much what i was thinking you are only allowing yourself 6 milliseconds to update and render if you want to maintain 60fps also i imagine there is something wrong in your draw calls if 2 images are causing this, you are not loading hte texture each frame are you? \$\endgroup\$
    – RoughPlace
    Commented Mar 27, 2013 at 19:05
  • \$\begingroup\$ @Yakyb. Thanks for your addition, reloading the sprites every frame might be an additional reason. \$\endgroup\$
    – danijar
    Commented Mar 27, 2013 at 20:39
5
\$\begingroup\$

well this is the game loop for minecraft, hope it helps!Also, I modified it a bit so it matches with your methods (originally it was tick();) :D

      this.requestFocus();
      long lastTime = System.nanoTime();
      double amountOfTicks = 60.0;
      double ns = 1000000000 / amountOfTicks;
      double delta = 0;
      long timer = System.currentTimeMillis();
      int frames = 0;
      while(isRunning) {
       long now = System.nanoTime();
       delta += (now - lastTime) / ns;
       lastTime = now;
       while(delta >= 1) {
        update();
        //updates++;
        delta--;
       }
       render();
       frames++;

       if(System.currentTimeMillis() - timer > 1000) {
        timer += 1000;
        frames = 0;
        //updates = 0;
       }
      }
      stop();
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .