Search code examples
c++sfml

window.display() alone toggles between the last and current buffer displayed


I made this code that shows a timer and pauses when you press spacebar:

#include <SFML/Graphics.hpp>
#include <iostream>

using namespace sf;
using namespace std;
void events();

bool pause, exitPause;
char key;
double timeFrame, timeTot = 0;
Clock timer;
Text text;
Font font;

RenderWindow window(VideoMode(800, 600), "Window", Style::Close);

int main()
{
    font.loadFromFile("C:/Windows/Fonts/arial.ttf");
    text.setFont(font);
    text.setCharacterSize(15);
    window.setFramerateLimit(120);
    while (window.isOpen())
    {
        for (Event event; window.pollEvent(event);) {
            if (event.type == Event::Closed)
                window.close();
            if (event.type == Event::TextEntered) {
                key = std::tolower(static_cast<char>(event.text.unicode));
                if (key == ' ') {
                    pause = !pause;
                    if (!pause) {
                        timer.restart();
                    }
                }
            }
        }
        if (!pause) {
            timeFrame = timer.restart().asSeconds();
            timeTot += timeFrame;
            text.setString(to_string(timeTot));
            window.clear();
            window.draw(text);
        }
        window.display();
    }
}

If you test, you will see something curious. When pausing by pressing the spacebar, window.display alternates between the last and the current displayed number.

But if I put window.clear and window.draw together with window.display, the problem does not happen.

        if (!pause) {
            timeFrame = timer.restart().asSeconds();
            timeTot += timeFrame;
            text.setString(to_string(timeTot));
        }
        window.clear();
        window.draw(text);
        window.display();

I thought windows.display, alone, would only show the last buffer. What is the problem?


Solution

  • The moment you pause you stop updating the draw buffers. SFML is always double-buffered, and in each iteration you always need to parse input, update whatever needs updating, redraw the "hidden" frame, and then flip the buffers. This is basically a "Game Loop" pattern.

    In your code you always parse input, update the timer and pause state based on that, and you always flip the buffers (with window.display()). You only redraw the "hidden" frame buffer if the state is not paused, however.

    So, you are seeing the expected output, and you found the correct solution.

    As an aside, there are indeed several style issues in your code, including uninitialized variables, which is always dangerous in C++.