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
/* 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?
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.