4
\$\begingroup\$

I'm learning C++ and openGL and have this program as a result from tutorials and playing around. The problem is that the main loop is running at "full speed", making the program unnecessarily cpu intensive. I have managed to make it only perform rendering every 16.7 ms or so, but the outside loop that is waiting to render still is iterating as fast as my computer can handle.

This is the full main.cpp: http://pastebin.com/KaCW7wZw

This is the main loop at line 95:

while (!terminate) {
    if (SDL_GetTicks() >= time_start + frame_rate)
    {
        time_start = SDL_GetTicks();
        while (SDL_PollEvent(&event))
        {
            if (event.type == SDL_QUIT) {
                terminate = true;
                break;
            }
        }

        glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        renderLoop(entities, &counter);
        SDL_GL_SwapWindow(m_window);;
        counter += 1.0f;
    }
}

I've tried googling and haven't found anything concrete (obviously), except that using some kind of sleep is bad design for these loops.

So how can I alter this to slow the whole thing down, and avoid having 100% cpu usage for a program that's not doing much at the moment?

\$\endgroup\$
5
\$\begingroup\$

Here's my game loop:

        double              lastTime        = game->GetGameTime().TotalTime();
        double              timeBehind      = 0.0;
        while( !end )
        {
            // Update the game time.
            game->GetGameTime().Update(); // Update game time values.
            flagEnd = game->HasEnded();   // Ignore this.
            timeBehind += game->GetGameTime().TotalTime() - lastTime; // Here we figure out how many updates behind we are. Update will not be called until this is a large enough value( the timestep we want. )
            lastTime = game->GetGameTime().TotalTime(); // Keep track of the last frame's time.

            // So, while we're behind more than one timestep, we'll update. So, even if drawing takes
            // about half a second, we update here until e have caught up. This way we'll never have 
            // slow updates because of drawing. No matter how slow the game draws, it'll always update based on time.
            while( timeBehind >= targetTimeStep )
            {
                // Update the game.
                game->Update();
                // Every time we update, we subtract a timestep from the amount we are behind.
                timeBehind -= targetTimeStep;
            }

                // Draw whether we update or not. ( You can remove all draws where there was no update, since nothing should be different. ) You could sleep here.
            game->Draw();
                // Swap the buffers.
            SwapInstanceBuffers();
        }

Here I have targetTimeStep at 1000 / 60. This is 60fps. The HUGE advantage of this game loop is that updates will be consistent. So, all your objects can move based on time, rather than frames. No matter how slow your game draws, your updates will still be consistent.

Here is where I learnt this from: http://gameprogrammingpatterns.com/game-loop.html It's a great article that's certainly worth your time to read.

\$\endgroup\$
  • \$\begingroup\$ This solution solves the rendering, but does not address the question's high CPU state. \$\endgroup\$ – rioki Apr 21 '14 at 19:16
  • \$\begingroup\$ @rioki The rendering? No, this solution solves the updating, which was by far the most important problem he was going to face. I mean, besides sleeping the thread, I don't really know how he'd lower the CPU state. It's either sleeping, or running. I even point out where the cpu is wasting time in this. \$\endgroup\$ – Ben Apr 21 '14 at 21:03
2
\$\begingroup\$

The above answers are basically correct, but I will take that different angle, you don't need to do anything. The moment you start actually rendering something you will be happy when your code actually runs at 60fps.

All my "real" games run with with a main loop that is unbounded. It keeps the entire thing responsive and I need to invest large amount of effort to get it to render at 60fps. The only thing I do is ensure that any logic is frame rate independent. (Though in recent years allot finds itself in other threads.)

But if you must you can implement a "yield", this basically works well with SDL_Delay(0). But this may have adverse effects, since that may be something up to 10 ms.

\$\endgroup\$
0
\$\begingroup\$

You could enable double buffering which would enable vsync (limit your framerate to whatever refresh rate your monitor supports (usually 60Hz, so 60fps)).

SDL_SetVideoMode(yourWidth, yourHeight, yourBpp, SDL_HWSURFACE  | SDL_DOUBLEBUF | SDL_FULLSCREEN);
\$\endgroup\$
  • \$\begingroup\$ I may be wrong, but as far as I can tell it's already doing that. \$\endgroup\$ – Anonymous Entity Apr 20 '14 at 19:55
  • \$\begingroup\$ This only works if the game is running faster or at 60fps. \$\endgroup\$ – Ben Apr 21 '14 at 0:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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