SFML鼠标点击检测

3
我正在使用SFML库编写一款游戏。 我有一些按钮,当我点击它们时,我想要做一些事情。 但是我遇到了一个问题,我不知道如何检测单击事件,而不是键盘按下或释放事件。 我编写了以下代码: 游戏循环:
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()))();
            }
        }
    }
}

例如,当我点击“播放”按钮时,将调用此方法:
void                            Menu::on_Jouer_clicked()
{
  std::cout << "fct jouer" << std::endl;
}

这是控制台中的结果:

~/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

函数调用次数过多。

你应该从一个更简单的例子/代码开始,比如一个简单的主函数和精灵,不要有太多花哨的东西。 - Hiura
你似乎在显示屏幕后立即清除它。通常我认为你应该先清除屏幕,然后绘制再显示。 - Galik
当然,在窗口系统中,它们通常在鼠标“释放”时执行操作。这意味着如果您不小心点击了错误的按钮,您可以在释放之前将鼠标移开。看起来您需要通过记录鼠标被按下的时间并测试鼠标被释放时经过的时间来手动确定鼠标单击 - Galik
我有一个很棒的提示给你,去谷歌一下:C++11 auto 关键字(它可以使迭代器更容易处理)。 - smoothware
好的,谢谢你 :) 我会去看它的! - DeepSiderZ
显示剩余2条评论
4个回答

4

这个问题不是很新,但是在我几个月前开始使用SFML时,我花了一些时间才得到答案。即使我读了鼠标和事件的文档"lol"。但我学习了更多的C ++,然后得出了以下结论:

{ //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.

如果你在应用程序中使用键盘,有一个“选项”可以使用,即:window.setKeyRepeatEnabled(false),但它只适用于键盘。(可能其他方法如操纵杆也适用,但我不确定)

唯一的问题是你必须为每个鼠标按钮都做这个设置,但我认为这并不是什么大问题。(除非你有那种计算器鼠标并且希望它对所有使用计算器鼠标的人都有效果,我不知道)

在你的情况下,只有一个播放按钮,因此由于通常只会点击一次,所以明显不需要buttonRelease。如果按多次,则必须使用它。


2

我不确定我是否记得正确,但是你可以使用类似以下代码来检查鼠标点击(还需指定左键或右键):

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

如果您希望指定点击位置,请使用以下代码,并检查其是否在所提到的按钮范围内:

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

然后您可以使用位置变量(position.x和position.y表示特定坐标)进行检查。

谢谢您的回答,好的方法就是将mouseEvent和keyboardEvent函数放在pollEvent循环中 :) - DeepSiderZ

0

这是我用来检测鼠标点击的代码:

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;
}

那样,您只会得到鼠标点击坐标,而不是鼠标仍然按下时的坐标。
auto position = Block_Until_Mouse_Click();
std::cout << position.x << " " << position.y << '\n';

它还会在一个紧密的循环中冻结整个应用程序,直到您释放按钮 :q。 - SasQ
是的,三年后看这个代码,无限循环是一个不好的想法。我不确定我的用例是什么,但我不建议像那样阻塞。SFML有更好的库调用来知道何时释放按钮:https://www.sfml-dev.org/tutorials/2.5/window-events.php#the-mousebuttonpressed-and-mousebuttonreleased-events - Trevor Hickey

0

每次我搜索鼠标事件时,它总是出现在谷歌搜索结果中。 :)

鼠标点击可以检测到鼠标按钮是否被按下或释放,就像你已经做的那样:

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

此外,它还可以进一步指定为左键或右键。

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

同样,可以通过event.mouseButton [X|Y]属性相对于窗口检索鼠标坐标。

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;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接