SFML community forums

Help => Window => Topic started by: racumin on October 14, 2009, 05:25:50 am

Title: Delayed display on Windows
Post by: racumin on October 14, 2009, 05:25:50 am
I am making a simple tetris game and developed my program in Linux. It runs smoothly - when I press a button, the state of the objects are displayed instantly. But when I compiled my code in Windows, the display is delayed. For example I pressed the left key 4 times, after some milliseconds (but I think less than a second), the object was moved 4 spaces already. In linux I can see it move 1 space every time I press the key. Why is that? The logic I used was:

Code: [Select]

int main() {
Gui gui;

while (gui.isRunning()) {
gui.clearBackground();      // window.clear()
gui.defaultMove();          // move the object 1 space down
gui.handleEvents();        // the while loop i saw in the tutorials
gui.drawGamePanel();        // draw objects here
gui.display();               // window.display()
}
return 0;
}


By the way, I initialized my window using:
Code: [Select]

VideoMode mode(GUI_WIDTH, GUI_HEIGHT, 32);
window = new RenderWindow(mode, "Falling Blocks", Style::Close);
window->SetFramerateLimit(60);

Image img_icon;
img_icon.LoadFromFile("icon.png");
window->SetIcon( img_icon.GetWidth(), img_icon.GetHeight(), img_icon.GetPixelsPtr());

if (!font.LoadFromFile("myfont.ttf")) {
cout << "failed to load font" << endl;
return;
}


Any ideas? Thanks!

[edit] Ok, I was able to disable the output from console using the option -mwindows But it still has a CPU usage of about 50.
Title: Delayed display on Windows
Post by: Laurent on October 14, 2009, 08:37:05 am
Your logic looks ok. Can you provide a complete (an minimal) example that reproduces the problem?

You can also upload your executable, so that we can test it directly.
Title: Delayed display on Windows
Post by: racumin on October 14, 2009, 09:22:15 am
How can I upload the exe?

These are my code snippets

Code: [Select]

void Gui::handleEvents() {
//listen for events
Event event;
while (window->GetEvent(event)) {
// a key is pressed
if (event.Type == Event::KeyPressed) {
switch (event.Key.Code) {
case Key::Escape:
if (gameStatus == STATUS_PLAYING) {
cout << "pausing game..." << endl;
gameStatus = STATUS_PAUSED;
} else if (gameStatus == STATUS_PAUSED) {
cout << "resuming game..." << endl;
gameStatus = STATUS_PLAYING;
} else {
cout << "closing window..." << endl;
running = false;
window->Close();
}

break;
case Key::Left:
if (gameStatus == STATUS_PLAYING) {
current_shape->moveLeft();
}
break;
case Key::Right:
if (gameStatus == STATUS_PLAYING) {
current_shape->moveRight();
}
break;
case Key::Down:
if (gameStatus == STATUS_PLAYING) {
moveDown();
}
break;
case Key::Space:
if (gameStatus == STATUS_PLAYING) {
current_shape->rotateClockwise();
}
break;

default:
cout << "ignoring pressed key..." << endl;
}
} else if (event.Type == Event::Closed) {
cout << "pressed close button, closing window..." << endl;
running = false;
window->Close();
}
}
}


One more thing, I am using the Clock class to determine if the current object should be moved down.

Code: [Select]


void Gui::defaultMove() {
//move shape down if status is STATUS_PLAYING
if ((clock.GetElapsedTime() >= sleepTime) && (gameStatus == STATUS_PLAYING)) {
clock.Reset();
moveDown();
}
}


My sleepTime is 1.0f and it decreases as the game level progresses
Title: Delayed display on Windows
Post by: Laurent on October 14, 2009, 09:33:25 am
Quote
How can I upload the exe?

You can use a free website like RapidShare or MegaUpload.

Quote
These are my code snippets

Well, a complete and minimal example that reproduces the problem would be much more useful. You'll probably even find the problem yourself by doing this. And if you don't, then I'll immediatly see what's wrong instead of spending hours trying to figure out what you're doing in your entire code ;)
Title: Delayed display on Windows
Post by: racumin on October 14, 2009, 09:37:32 am
What do you mean by complete and minimal example? Do you mean the source code?
Title: Delayed display on Windows
Post by: Laurent on October 14, 2009, 09:47:27 am
I mean something as tiny as possible, that I can compile after pasting it directly in my EDI, and that shows the same problem. In other words, removing from your source code everything that is not related to the error, so that we can focus on what's important.
Title: Delayed display on Windows
Post by: racumin on October 21, 2009, 11:58:29 am
Hi I tried to look for the problem here. The reason (I think) that displaying was delayed was because when I play the game, the CPU usage for it was about 50. (using ctrl + alt + delete). The psuedo code here is

Code: [Select]

int main() {
   Gui gui;

   while (gui.isRunning()) {
      gui.clearBackground();      // window.clear()
      gui.defaultMove();          // move the object 1 space down
      gui.handleEvents();        // the while loop i saw in the tutorials
      gui.drawGamePanel();        // draw objects here
      gui.display();               // window.display()
   }
   return 0;
}



Now, I commented all the logic stuffs like this:

Code: [Select]

int main() {
   Gui gui;

   while (gui.isRunning()) {
      gui.clearBackground();      // window.clear()
 //     gui.defaultMove();          // move the object 1 space down
      gui.handleEvents();        // the while loop i saw in the tutorials
 //     gui.drawGamePanel();        // draw objects here
      gui.display();               // window.display()
   }
   return 0;
}


The CPU then was 0, meaning I have a bug in the program. So, what I thought to be the problem was that the loop never sleeps. I assumed that window.display() with frame limit = 60 will do the job but it did not. The other methods were called every loop (loop was called maybe several times a millisecond??)

So I tried to put a sleep in my code:

Code: [Select]

int main() {
   Gui gui;

   while (gui.isRunning()) {
      Sleep(0.001f);
      gui.clearBackground();      // window.clear()
      gui.defaultMove();          // move the object 1 space down
      gui.handleEvents();        // the while loop i saw in the tutorials
      gui.drawGamePanel();        // draw objects here
      gui.display();               // window.display()
   }
   return 0;
}


It also failed. CPU was also about 50. Now for questions

1. How does the window.display() with window.setFrameLimit(60) work?
2. If you set the frame limit to 60, do you still need to draw ALL objects in the canvas? (window.Draw(Rectangle))
3. Do I really need to put a Sleep() in every loop? If so, what can be its value?
4. The output was also seen in the console. Does this matter? If so, how can I disable output from console? (using windows and code::blocks)

Thanks!

[edit] I was able to disable the output from console using -mwindows but it still consumes a lot of CPU (about 50)
Title: Delayed display on Windows
Post by: Laurent on October 21, 2009, 12:25:46 pm
Quote
1. How does the window.display() with window.setFrameLimit(60) work?

It calls sf::Sleep(1/60 - frameTime).

Quote
2. If you set the frame limit to 60, do you still need to draw ALL objects in the canvas? (window.Draw(Rectangle))

Sorry I don't get it. What's the relation between the framerate limit and the objects you draw?

Quote
3. Do I really need to put a Sleep() in every loop? If so, what can be its value?

No you don't :) (see answer 1).

Quote
4. The output was also seen in the console. Does this matter? If so, how can I disable output from console? (using windows and code::blocks)

If you want to hide the console, you have to select a "Win32 GUI" project in Code::Blocks.
If you want to show the console but hide the error ouput, you can redirect std::cerr to something else than the console.
Title: Delayed display on Windows
Post by: racumin on October 21, 2009, 12:36:25 pm
Thanks for the answers. So, I am assured that the whole loop will just be called at most 60 times per second because of the Sleep in the window.Display().

Now, I explored my code and noticed that a single draw method was enough to boost my cpu usage to about 20 - 30. In my loop, I just did this:

Code: [Select]

Shape blocksPanel = Shape::Rectangle(
(GRID_WIDTH + 2) * BLOCK_SIZE,
BLOCK_SIZE * 8,
(GRID_WIDTH + 7) * BLOCK_SIZE,
(GRID_HEIGHT_LIMIT + 1) * BLOCK_SIZE,
BG_COLOR,
OUTLINE,
OUTLINE_COLOR);
window->Draw(blocksPanel);


Is this acceptable? Is the CPU usage of 50 acceptable when running a simple application? By the way, I used a pointer for the RenderWindow

Code: [Select]

RenderWindow *window;
VideoMode mode(GUI_WIDTH, GUI_HEIGHT, 32);
window = new RenderWindow(mode, "Falling Blocks", Style::Close);


Does that affect the performance of the application?

[edit] Hmmm. I think that my PC is responsible for the slow display. I tried my program in a different computer and it runs smoothly.

Thanks anyways...