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

Author Topic: Getting things to happen once inside the game loop.  (Read 1477 times)

0 Members and 1 Guest are viewing this topic.

Riser

  • Newbie
  • *
  • Posts: 33
    • View Profile
Getting things to happen once inside the game loop.
« on: August 05, 2020, 02:59:16 am »
I have two problems that are loosely related and I didn't want to create two separate threads into separate sub-forums:

The first is that I have a number of buttons, when the left mouse button is clicked while the cursor is inside a button's hitbox, the scene is changed depending on which button is clicked:

for (int j = init; j < limit; j++) {
                collision = buttons[j].button_collision();

                if (sf::Mouse::isButtonPressed(sf::Mouse::Button::Left) == true) {
                //Button logic goes here.
                }
                       
}
 

The problem is, when the mouse button is pressed, and the scene changes, in the fraction of a second that I'm still holding the mouse button down and the cursor happens to be on another button in the new scene, that button will be clicked and the scene will change again quickly even if that's not what I want.

So I tried changing the code to the following:

for (int j = init; j < limit; j++) {
                collision = buttons[j].button_collision();

                        if (e.type == sf::Event::MouseButtonReleased) {
                                if (e.mouseButton.button == sf::Mouse::Left) {
                                //Button logic goes here.
                                }
                         }
}
 

Now, the scene only changes when the button is clicked then released, but, for fraction of a second, if the cursor happens to be hovering on a button when the scene changes, that button will also be "clicked" even though the mouse button is released when that happens.

It's weird, the code does something completely different than the previous one, but I still end up with what is essentially the same problem.

Now that leaves with the second problem, which is a simple one:

for (int j = init; j < limit; j++) {
                collision = buttons[j].button_collision();

                if (collision == true) {
                        m_hover.play(); //'m_hover' is a blip sfx that is supposed to play when the cursor hovers on a button.
                }

                if (sf::Mouse::isButtonPressed(sf::Mouse::Button::Left) == true) {
                //Button logic goes here.
                }
                       
}
 

But since this code is included in the game loop, the sound effect ends up playing every single frame.


So my two problems are essentially the same: Executing an instruction only on the first frame in which collision=true, and not executing it again until collision=false.

How do I register a single mouse press (Or a click preferably if possible, meaning a press then a release)?
And how do I get a sound effect to play only the first time it's condition is met, until it returns to be false again?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Re: Getting things to happen once inside the game loop.
« Reply #1 on: August 05, 2020, 08:28:32 am »
If all this code does is to check which button is clicked, and execute the corresponding action, then I would do it this way:

// THIS IS PSEUDO-CODE

// event loop! never use sf::Event instances outside
sf::Event event;
while (window.pollEvent(event))
{
    if (event is MouseButtonReleased and button is Left)
    {
        for each GUI button...
        {
            if (mouse cursor (event.mouseButton.x/y) is inside button)
            {
                execute action...
                break;
            }
        }
    }
}

By checking the button released event, you make sure that your code is only executed once. And by breaking the loop after finding the clicked button, you make sure that you don't check other buttons that the click would have brought below the mouse cursor (new scene).
Laurent Gomila - SFML developer