Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Basic game loop question  (Read 5212 times)

0 Members and 1 Guest are viewing this topic.

Dr_Asik

  • Newbie
  • *
  • Posts: 13
    • View Profile
Basic game loop question
« on: November 04, 2009, 06:15:04 am »
Hello, I am coding my first non-XNA game and using SFML in C++. XNA took care of the game loop but now I have to code my own.

I have come up with this:

Code: [Select]
   Clock clock;
    float timeBetweenFrames = 1000.0f / (float)updatesPerSecond_;

    while (app_.GetEvent(event)) {
        if (event.Type == Event::Closed) {
            app_.Close();
        }
    }

    while (app_.IsOpened()) {
        clock.Reset();
        Event event;

        update(timeBetweenFrames);
        draw(timeBetweenFrames);

        while (clock.GetElapsedTime() < timeBetweenFrames) {
            sf::Sleep(0.0005f);
        }
    }
(Where app_ is a RenderWindow and updatesPerSecond_ is an int, here 60.)

The problem here is that the window becomes non-responsive. I don't really get it as events will still get processed [updatesPerSecond_] times per second (in my case 60). Do I really need to be constantly polling for events? In that case, wouldn't a dedicated thread be more appropriate?

In any case, I "fixed" the problem by removing the call to sleep and replacing it with constant polling of events.

Code: [Select]
   Clock clock;
    float timeBetweenFrames = 1000.0f / (float)updatesPerSecond_;


    while (app_.IsOpened()) {
        clock.Reset();
        Event event;

        update(timeBetweenFrames);
        draw(timeBetweenFrames);

        while (clock.GetElapsedTime() < timeBetweenFrames) {
            while (app_.GetEvent(event)) {
                if (event.Type == Event::Closed) {
                    app_.Close();
                }
            }
        }
    }


This is responsive, and draw and update should be called [updatesPerSecond_] times per second.

Still, I'm a bit lost. What if some part of my game needs to be updated as often as possible? For instance, the audio engine, or even just the graphics. Anytime I'm doing some game processing, I am not polling events, so will the window become non-responsive again?

JannoT

  • Guest
Basic game loop question
« Reply #1 on: November 04, 2009, 07:48:26 am »
Polling for event's is fast, and i think you should do it every time you plan on calling sf::RenderWindow->Display();

Dr_Asik

  • Newbie
  • *
  • Posts: 13
    • View Profile
Basic game loop question
« Reply #2 on: November 04, 2009, 08:35:15 am »
Damn, just found out one big mistake with the code I posted:

Code: [Select]
float timeBetweenFrames = 1000.0f / (float)updatesPerSecond_;

This will lead to a timeBetweenFrames 1000 times too large. :lol:  Should be:

Code: [Select]
float timeBetweenFrames = 1.0f / (float)updatesPerSecond_;

This explains the non-responsiveness of my first code example. So apparently it has nothing to do with polling for events only once per loop.

So, uh, problem fixed I guess.  :)

While we're at it, I have a question about the following article on
http://dewitters.koonsolo.com/gameloop.html

Here is the part I don't get:

Quote
Our first solution, FPS dependent on Constant Game Speed, has a problem when running on slow hardware. Both the game speed and the framerate will drop in that case. A possible solution for this could be to keep updating the game at that rate, but reduce the rendering framerate. This can be done using following game loop:

   
Code: [Select]
   const int TICKS_PER_SECOND = 50;
    const int SKIP_TICKS = 1000 / TICKS_PER_SECOND;
    const int MAX_FRAMESKIP = 10;
       
    DWORD next_game_tick = GetTickCount();
    int loops;
   
    bool game_is_running = true;
    while( game_is_running ) {

        loops = 0;
        while( GetTickCount() > next_game_tick && loops < MAX_FRAMESKIP) {
            update_game();
           
            next_game_tick += SKIP_TICKS;
            loops++;
        }
       
        display_game();
    }

The game will be updated at a steady 50 times per second, and rendering is done as fast as possible. Remark that when rendering is done more than 50 times per second, some subsequent frames will be the same, so actual visual frames will be dispayed at a maximum of 50 frames per second. When running on slow hardware, the framerate can drop until the game update loop will reach MAX_FRAMESKIP. In practice this means that when our render FPS drops below 5 (= FRAMES_PER_SECOND / MAX_FRAMESKIP), the actual game will slow down.


He says "The game will be updated at a steady 50 times per second, and rendering is done as fast as possible." However, looking at that code, it seems display_game() is called a maximum of once per loop, while update_game() may be called several times being in that inner while loop. In other words it looks like it is the contrary of what he's saying: the game will be updated as often as possible, while the rendering will take place a fixed number of times per second.

Am I right (I hope not)?

Calmatory

  • Newbie
  • *
  • Posts: 16
    • View Profile
Basic game loop question
« Reply #3 on: November 04, 2009, 09:02:53 am »
Let's just say that the method used there isn't the most optimal or best available. (For example the frame delaying should be with Sleep(int ms) function, to preserve system resources and update the game world only once per frame).

With SFML you can use SetFramerateLimit() and GetFrameTime() methods(sf::Window) for example.

Of couse it's quite trivial to come up with your own functions for these, if you want to.
The amount of effort we put into something arbitrary we do in our everyday lives is proportional to the amount we gain from it. It's fascinating how this applies to everything in our lives. Your task is to try to enjoy and make the most out of it.

Tank

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1486
    • View Profile
    • Blog
    • Email
Re: Basic game loop question
« Reply #4 on: November 04, 2009, 09:15:39 am »
Quote from: "Dr_Asik"
Still, I'm a bit lost. What if some part of my game needs to be updated as often as possible? For instance, the audio engine, or even just the graphics. Anytime I'm doing some game processing, I am not polling events, so will the window become non-responsive again?

Normally things don't need to get "updated as often as possible".

For example, if you've locked your framerate to 60 per second, then you can process your calculations with a factor that depends on the frame time. Let's say you want to get the number 60 just by adding 1:

1) 1 + 1 + 1 + ... + 1
2) 60 * 1

Which one would you prefer? ;)

The drawback here is that this can get a little unprecise. With the 2nd method mentioned above, you never ever can get numbers below 60, just above (if the frame time needs longer than 1 / 60, ergo the frame rate drops below 60).

You have to ask yourself if you need this. If so, there're several solutions:

- Increase FPS (but you still should draw with the screen's vsync).
- Use a separate thread to do fine calculations or even all.

Time to choose, Mr. Freeman. ;)

 

anything