【问题标题】:SFML Mouse click detectionSFML 鼠标点击检测
【发布时间】:2015-08-03 01:07:56
【问题描述】:

我正在使用 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();
    }
}

菜单.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;
}

这是 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

函数调用次数过多。

【问题讨论】:

  • 您可能应该从一个更简单的示例/代码开始,例如一个带有精灵的简单主代码,没有什么花哨的。
  • 我的示例代码太复杂了?
  • 您似乎在显示屏幕后立即清除屏幕。通常我认为您会清除屏幕,绘制然后显示。
  • 是的,我已经改变了,因为它更符合逻辑。但这不是我的问题^^"
  • 当然。 FWIW 在窗口系统中它们通常在鼠标释放 时执行action。这意味着如果您不小心点击了错误的按钮,您可以在释放之前将鼠标移开。看来您必须通过记录鼠标按下的时间并测试鼠标释放时经过了多长时间来手动计算鼠标单击 .

标签: c++ events click mouse sfml


【解决方案1】:

这个问题不是最近才出现的,但是当我几个月前开始使用 sfml 时,我挣扎了一段时间才得到答案。即使我阅读了鼠标和事件“lol”的文档。但我改进了,这里是代码:

static bool lock_click; //create a bool variable for lock the click.
if (evnt.type == sf::Event::MouseButtonPressed) //Mouse button Pressed
{
    if (evnt.mouseButton.button == sf::Mouse::Left && lock_click != true) //specifies
    {
        //stuff before locking...
        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. 
    }
}
if (evnt.type == sf::Event::MouseButtonReleased) //Mouse button Released now.
{
    if (evnt.mouseButton.button == sf::Mouse::Left) //specifies the held button that we put before.
    {
        lock_click = false; //unlock when the button(lmb) has been released.
    }
}

如果您在应用程序中使用键盘,则有一个“选项”window.setKeyRepeatEnabled(false)但是我之前说过,它只有 适用于键盘(或者至少不适合鼠标!)

我看不出有什么比这更有效的方法,因为您可以只使用一个按钮,而让另一个正常。就像用 Lmb 使用近战和用 Rmb 使用自动远程东西一样。 (如果你想要一些特定的时间,你也可以制作计时器。)

【讨论】:

    【解决方案2】:

    不确定我是否记错了,但你不能用这样的东西来检查鼠标点击(同时指定左键或右键)

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

    如果您希望您的检查指定点击的位置,那么您可以在下面使用它并检查它是否在提到的按钮的范围内:

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

    然后可以使用位置变量(具体坐标的position.x和position.y)来检查。

    【讨论】:

    • 谢谢你的回答,好办法就是把 mouseEvent 和 keyboardEvent 函数放在 pollEvent 循环中 :)
    【解决方案3】:

    这是我用来检测鼠标点击的方法:

    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
    • 是的,3 年后再看这个,无限循环是个坏主意。我不确定我的用例是什么,但我不建议这样阻塞。 SFML 有更好的库调用来了解按钮何时被释放:sfml-dev.org/tutorials/2.5/…
    【解决方案4】:

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

    可以检测鼠标点击是按下还是释放鼠标按钮,就像你已经在做的那样

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

    【讨论】:

      猜你喜欢
      • 2012-06-13
      • 2020-04-18
      • 2021-09-06
      相关资源
      最近更新 更多