Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

This question already has an answer here:

My game-loop looks like this:

        public void run() {
            init();

            final double amountOfTicks = 60.0;
            double ns = 1000000000.0 / amountOfTicks;
            long time = System.currentTimeMillis();
            long lastTime = System.nanoTime();
            long now = 0;
            double delta = 0;
            int tickCount = 0;
            int renderCount = 0;

            while(running) {

                now = System.nanoTime();
                delta += (now - lastTime) / ns;
                lastTime = now;

                if(delta >= 1) {
                    tick();
                    tickCount++;
                    delta--;
                    render();
                    renderCount++;
                }


                if(System.currentTimeMillis() - time >= 1000) {
                    time += 1000;
                    System.out.println(tickCount + " Ticks, " + renderCount + " FPS");
                    tickCount = 0;
                    renderCount = 0;
                }


            }
            stop();

        }

In the variable "amountOfTicks" i can set how many ticks i want per second. The amountOfTicks are here the same as the fps which i have. With this solution my console prints "60Ticks, 60 FPS", but the problem is, that the CPU-performance with this method is too low. I have only 60 Ticks and only 60 FPS, but the whole while-loop is still running through as fast as my pc can.

The only thing how i can improve the cpu-performance is, if i let the thread for 1ms or so sleeping. But is this solution not dirty? This solution will maybe work on my (relative good pc), but on a other with with less CPU-performance the 1ms sleep maybe are waste, because of this the game maybe can not reach the 60FPS of this?

share|improve this question

marked as duplicate by Anko, Josh Petrie Feb 3 at 16:18

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

2  
1  
You need to draw statistics of the users' cpu performance. If time passed < expected_time... sleep expected_time - time_passed –  Zehelvion Feb 2 at 20:55
add comment

1 Answer 1

up vote 2 down vote accepted

There are two ways of achieving this, one would be a variable timestep, with that the game would seem consistent, regardless how fast the computer of the player is.

The other way would be a fixed timestep, there you will know how long each single timestep would be, also regardless how fast the computer is.

For more information on Game loops you can look at this site.

Here are some examples:

Variable timestep

public void gameLoop()
{
   long lastLoopTime = System.nanoTime();
   final int TARGET_FPS = 60;
   final long OPTIMAL_TIME = 1000000000 / TARGET_FPS;   

   // keep looping round til the game ends
   while (gameRunning)
   {
      // work out how long its been since the last update, this
      // will be used to calculate how far the entities should
      // move this loop
      long now = System.nanoTime();
      long updateLength = now - lastLoopTime;
      lastLoopTime = now;
      double delta = updateLength / ((double)OPTIMAL_TIME);

      // update the frame counter
      lastFpsTime += updateLength;
      fps++;

      // update our FPS counter if a second has passed since
      // we last recorded
      if (lastFpsTime >= 1000000000)
      {
         System.out.println("(FPS: "+fps+")");
         lastFpsTime = 0;
         fps = 0;
      }

      // update the game logic
      doGameUpdates(delta);

      // draw everyting
      render();

      // we want each frame to take 10 milliseconds, to do this
      // we've recorded when we started the frame. We add 10 milliseconds
      // to this and then factor in the current time to give 
      // us our final value to wait for
      // remember this is in ms, whereas our lastLoopTime etc. vars are in ns.
      try{Thread.sleep( (lastLoopTime-System.nanoTime() + OPTIMAL_TIME)/1000000 )};
   }
}

Fixed timestep

private void gameLoop()
{
   //This value would probably be stored elsewhere.
   final double GAME_HERTZ = 30.0;
   //Calculate how many ns each frame should take for our target game hertz.
   final double TIME_BETWEEN_UPDATES = 1000000000 / GAME_HERTZ;
   //At the very most we will update the game this many times before a new render.
   //If you're worried about visual hitches more than perfect timing, set this to 1.
   final int MAX_UPDATES_BEFORE_RENDER = 5;
   //We will need the last update time.
   double lastUpdateTime = System.nanoTime();
   //Store the last time we rendered.
   double lastRenderTime = System.nanoTime();

   //If we are able to get as high as this FPS, don't render again.
   final double TARGET_FPS = 60;
   final double TARGET_TIME_BETWEEN_RENDERS = 1000000000 / TARGET_FPS;

   //Simple way of finding FPS.
   int lastSecondTime = (int) (lastUpdateTime / 1000000000);

   while (running)
   {
      double now = System.nanoTime();
      int updateCount = 0;

      if (!paused)
      {
         //Do as many game updates as we need to, potentially playing catchup.
         while( now - lastUpdateTime > TIME_BETWEEN_UPDATES && updateCount < MAX_UPDATES_BEFORE_RENDER )
         {
            updateGame();
            lastUpdateTime += TIME_BETWEEN_UPDATES;
            updateCount++;
         }

         //If for some reason an update takes forever, we don't want to do an insane number of catchups.
         //If you were doing some sort of game that needed to keep EXACT time, you would get rid of this.
         if ( now - lastUpdateTime > TIME_BETWEEN_UPDATES)
         {
            lastUpdateTime = now - TIME_BETWEEN_UPDATES;
         }

         //Render. To do so, we need to calculate interpolation for a smooth render.
         float interpolation = Math.min(1.0f, (float) ((now - lastUpdateTime) / TIME_BETWEEN_UPDATES) );
         drawGame(interpolation);
         lastRenderTime = now;

         //Update the frames we got.
         int thisSecond = (int) (lastUpdateTime / 1000000000);
         if (thisSecond > lastSecondTime)
         {
            System.out.println("NEW SECOND " + thisSecond + " " + frameCount);
            fps = frameCount;
            frameCount = 0;
            lastSecondTime = thisSecond;
         }

         //Yield until it has been at least the target time between renders. This saves the CPU from hogging.
         while ( now - lastRenderTime < TARGET_TIME_BETWEEN_RENDERS && now - lastUpdateTime < TIME_BETWEEN_UPDATES)
         {
            Thread.yield();

            //This stops the app from consuming all your CPU. It makes this slightly less accurate, but is worth it.
            //You can remove this line and it will still work (better), your CPU just climbs on certain OSes.
            //FYI on some OS's this can cause pretty bad stuttering.
            try {Thread.sleep(1);} catch(Exception e) {} 

            now = System.nanoTime();
         }
      }
   }
}
share|improve this answer
add comment

Not the answer you're looking for? Browse other questions tagged or ask your own question.