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

Author Topic: Events outside loop  (Read 7325 times)

0 Members and 3 Guests are viewing this topic.

Ganitzsh

  • Newbie
  • *
  • Posts: 1
    • View Profile
    • Email
Events outside loop
« on: March 26, 2014, 03:03:26 pm »
Hi,

Im working on a game, a snake-like but I'm experiencing issues with events.
My design is the following;
I have a Core containing the game logic. (positions, food, snake body)
A dynamicaly linked SFML module to display the window and play the game
A game loop outside the SFML module

Basically, my SFML module create a window when I create the instance and display the snake on the sf::RenderWindow in the game loop located on the main.
I was wondering if there was an other way to handle input in a window than create a loop on RenderWindow::pollEvent().

Here's a sample of code:

/* Called inside loop */
void    SFMLModule::refreshScreen()
{
  if (!_window->setActive())
    _window->setActive(true);
  input(); /* <----- input method (see below) */
  _window->display();
  _window->clear();
  render();
  _clock.restart();
}

/* Handling input */
void SFMLModule::input()
{
  while (_window->pollEvent(_event))
  {
    if (_event.type == sf::Event::Closed)
    {
      _window->close();
      _core.setDone(true);
    }
    else if (_event.type == sf::Event::KeyPressed)
    {
      if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
      {
        _window->close();
        _core.setDone(true);
      }
      if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
        _core.keyPressed(LEFT);
      if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
        _core.keyPressed(RIGHT);
    }
  }
}

/* game loop inside main */
# define TIME_PER_FRAME 70000
while (!core->isDone())
{
   library->refreshScreen();
   if (!core->getStop())
      core->move();
   usleep(TIME_PER_FRAME);
}
 

My problem is in the
SFMLModule::refreshScreen()
method.
Since it's called in a loop, the input method will also create a loop and I suspect this is the root of the lag I have at runtime. Am I wrong?
Also, my sf::RenderWindow does not display correctly sometimes, there's a transparent zone at the bottom.

Thanks  :)

Julien
« Last Edit: March 26, 2014, 03:05:27 pm by Ganitzsh »

Ixrec

  • Hero Member
  • *****
  • Posts: 1241
    • View Profile
    • Email
Re: Events outside loop
« Reply #1 on: April 07, 2014, 12:03:53 am »
Looping over the event queue within your main while(window is open) loop is perfectly normal and shouldn't be causing any problems unless you have hundreds of events firing every frame, which shouldn't happen.

I have no idea about the "transparent zone" thing, could you be more specific?
« Last Edit: April 07, 2014, 12:06:16 am by Ixrec »

dabbertorres

  • Hero Member
  • *****
  • Posts: 505
    • View Profile
    • website/blog
Re: Events outside loop
« Reply #2 on: April 07, 2014, 02:37:51 am »
/* Called inside loop */
void    SFMLModule::refreshScreen()
{
  if (!_window->setActive())
    _window->setActive(true);
  input(); /* <----- input method (see below) */
  _window->display();
  _window->clear();
  render();
  _clock.restart();
}

Why are you calling display, then clear, then draw?
The order should always be: clear, draw, display.
Yeah, this is kind of in that order, but, put the display call after render, see if that fixes your problem.

Is there a tutorial or somewhere you read from that gives you that order?

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11034
    • View Profile
    • development blog
    • Email
Re: Events outside loop
« Reply #3 on: April 07, 2014, 08:52:37 am »
Why are you calling display, then clear, then draw?
The order should always be: clear, draw, display.
In practice it doesn't really matter, since SFML is using double buffering, but from a code design standpoint it should be clear, draw, display.

Looping through events doesn't take a lot of time and having an event loop inside the main loop is the way to go (see the example on the docs). There are rare cases where mouse drivers generate a lot of events when moving the mouse on the window, however this is more often an bad behavior of drivers.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Events outside loop
« Reply #4 on: April 07, 2014, 09:46:31 am »
Calling display first makes sense. Even if in practice it won't make a significant difference, it might be a good idea: after you draw the GPU is busy processing all the drawing commands and if you display() right after that, it might block until everything is processed.

Calling display() later leaves the opportunity for the CPU to do something useful (like updating the game logic) while the GPU is busy, instead of blocking the application.
Laurent Gomila - SFML developer

didii

  • Full Member
  • ***
  • Posts: 122
    • View Profile
Re: Events outside loop
« Reply #5 on: April 17, 2014, 05:18:44 pm »
Calling display() later leaves the opportunity for the CPU to do something useful (like updating the game logic) while the GPU is busy, instead of blocking the application.
Isn't it entirely the GPU's task to display? Why should the CPU wait for the GPU when calling display()?

zsbzsb

  • Hero Member
  • *****
  • Posts: 1409
  • Active Maintainer of CSFML/SFML.NET
    • View Profile
    • My little corner...
    • Email
Re: Events outside loop
« Reply #6 on: April 17, 2014, 05:35:18 pm »
Because OpenGL is not multithreaded, hence display() is blocking (this is where vsync also does its job) and it will cause the CPU to rest while the GPU is doing the job of swapping buffers.
Motion / MotionNET - Complete video / audio playback for SFML / SFML.NET

NetEXT - An SFML.NET Extension Library based on Thor

didii

  • Full Member
  • ***
  • Posts: 122
    • View Profile
Re: Events outside loop
« Reply #7 on: April 17, 2014, 05:42:46 pm »
But the CPU and GPU work asynchronous, so why would the CPU wait if it only needs to add a command to the GPU's queue? Or does calling display() imply you want it to display immediately rather than when it's finished?



To answer the question from the OP. No, it isn't abnormal to have a nested while loop. A typical loop would look like
while (window.isOpen()) {
    sf::Event ev;
    while (window.pollEvent(ev)) {
        // process events
    }
}

And a couple of remarks:
  • Try to avoid using global variables and #defines.
  • Don't mix real-time input and events: sf::Keyboard::isKeyPressed(...) is real-time. This returns true if the key is pressed at that exact moment. event.key.code == sf::Keyboard::... returns true at least once inside the event loop if the key was pressed since the previous event loop.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Events outside loop
« Reply #8 on: April 17, 2014, 07:55:27 pm »
window.display() implicitly calls glFinish(), which blocks until the pending commands have been processed and the current frame has been displayed on the monitor. So while the GPU is busy doing all this stuff, the CPU is potentially idle -- unless you give it something useful to do.
Laurent Gomila - SFML developer

didii

  • Full Member
  • ***
  • Posts: 122
    • View Profile
Re: Events outside loop
« Reply #9 on: April 18, 2014, 03:11:17 pm »
Ok, thanks for the explanation :)

The Terminator

  • Full Member
  • ***
  • Posts: 224
  • Windows and Mac C++ Developer
    • View Profile
Events outside loop
« Reply #10 on: April 18, 2014, 08:36:17 pm »
Is OpenGL ever going to be multithreaded? Or is it sort of out of its scope?
Current Projects:
Technoport