Reputation: 67
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
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
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
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
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