DeepSiderZ
DeepSiderZ

Reputation: 67

SFML Mouse click detection

I'm coding a game with SFML library. I have some buttons and when I click on, I want to do something.

But I have a probleme, I don't know how to detect a simple click, not key released or key pressed, just a click.

I write this code :

Game loop :

void                            GameEngine::gameLoop()
{
  Menu                                  menu(_win);

  while (_win.isOpen() && gl_quit == false)
    {
      sf::Event         event;
      while (_win.pollEvent(event))
        {
          if (event.type == sf::Event::Closed)
            _win.close();
        }
      menu.mouseEvent(event);
      menu.keyboardEvent();

      menu.calcul();
      menu.reDraw();

      _win.display();
      _win.clear();
    }
}

Menu.cpp

bool                            Menu::mouseEvent(sf::Event &event)
{
  if (event.type == sf::Event::MouseButtonReleased)
    {
      if (event.mouseButton.button == sf::Mouse::Left)
        {
          for (std::map<std::string, Button *>::iterator it = _buttons.begin();
               it != _buttons.end(); ++it)
            {
              if (it->second->collide(sf::Mouse::getPosition(_win)))
                (this->*(it->second->getAction()))();
            }
        }
    }
}

And for example when I click on the "Play" button, this method is called :

void                            Menu::on_Jouer_clicked()
{
  std::cout << "fct jouer" << std::endl;
}

And the this is the result in consol :

~/Projet/gametest :./game 
fct jouer
fct jouer
fct jouer
fct jouer
fct jouer
fct jouer
fct jouer
fct jouer
fct jouer
fct jouer
fct jouer
fct jouer
fct jouer
fct jouer
fct jouer
fct jouer

The function is called too many times.

Upvotes: 3

Views: 16727

Answers (4)

Nazzel
Nazzel

Reputation: 41

This question is not very recent, but i struggle for some time to get the answer when i started sfml a few months ago. Even when i read the documentation of the mouse and events "lol". But i studied more c++, and i came with this:

{ //Inside the 'while (pollEvent())' scope or something else.
  static bool lock_click; // Create a bool variable for locking the click.
  if (evnt.type == sf::Event::MouseButtonPressed) //Mouse button Pressed
  {
      if (evnt.mouseButton.button == sf::Mouse::Left && lock_click != true) //specifies
      {
          /* your code here*/
          std::cout << "lmb-pressed" << std::endl; // usually this will show in a  loop because is being pressed;
          lock_click = true; //And now, after all your code, this will lock the loop and not print "lmb" in a x held time. 
          /* or here idk */
      }   
  }

  if (evnt.type == sf::Event::MouseButtonReleased) //Mouse button Released now.
  {
      if (evnt.mouseButton.button == sf::Mouse::Left) //specifies the held button       again. (You can make a variable for that if you want)
      {
          lock_click = false; //unlock when the button has been released.
      }
  } //Released Scope
} //PollEvent Scope.

There is a "option" if you are using keyboard in your app that is: window.setKeyRepeatEnabled(false), but it only works for keyboards. (Maybe other methods like joystick works too but i'm not sure)

The only problem is that you have to make this for each mouse button but i think it's not big deal. (unless you have that type of calculator mouse and you want it to work fine for everyone that have calculator mouses too idk)

In your case just it's a play button so it's clearly not necessary the buttonRelease since it's only clicked once normally, if it's more than one time pressed you will have to use it.

Upvotes: 4

MORTAL
MORTAL

Reputation: 383

it always comes on google search when i searched for the mouse events. :)

the mouse clicks can be detected whether the mouse button was pressed or released as what you already did in

if (event.type == sf::Event::MouseButtonReleased)

also, it can be specified further as left or right button.

if (event.mouseButton.button == sf::Mouse::Left)

similarly the mouse coordinates can be retrieved relative to the window by event.mouseButton [X|Y] properties.

if (event.type == sf::Event::MouseButtonPressed)
{
    if (event.mouseButton.button == sf::Mouse::Left)
    {
        std::cout << "mouse x: " << event.mouseButton.x << std::endl;
        std::cout << "mouse y: " << event.mouseButton.y << std::endl;
    }
}

Upvotes: 0

Trevor Hickey
Trevor Hickey

Reputation: 37914

Here is what I use to detect just a mouse click:

sf::Vector2i Block_Until_Mouse_Click(){

    static bool pressed=false;
    sf::Vector2i position;
    while (true){

      if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
      {
          if (!pressed){
            position = sf::Mouse::getPosition();
            pressed=true;
            break;
          }
      }
      else{
        pressed = false;
      }   
    }

    return position;
}

That way, you only get mouse click coordinates, and not coordinates when the mouse is still down.

auto position = Block_Until_Mouse_Click();
std::cout << position.x << " " << position.y << '\n';

Upvotes: 0

christopherhernandez
christopherhernandez

Reputation: 67

Not sure if I remember correctly but can't you use something like this to check for a mouse click (Also specify left or right click)

if (event.type == sf::Event::MouseButtonPressed)

If you want your check to specify where a click is then you can use this below and check if it is within the bounds of the buttons mentioned:

sf::Vector2i position = sf::Mouse::getPosition();

Then you can use the position variable (position.x and position.y for the specific coordinates) to check.

Upvotes: 2

Related Questions