SFML 2.0中的重复重复

时间:2013-07-26 19:00:55

标签: c++ events keyboard sfml

如果刚刚在SFML中按下(未保持)某个键,或者是模仿这种效果的方法,有没有办法接收?

我在这里调查我的活动,

while (window.pollEvent(event));

然后在循环中,超出范围,但同样的事件,我读到:

if (event.type == sf::Event::KeyPressed)
{
    if (event.key.code == sf::Keyboard::Up)
    {
        decision--;
        if (decision < 0)
        decision = CHARACTER_MAX - 1;
    }
}

当按住向上箭头时,这会使decision连续递减。使用sf::event s,我可以在第一次按下时读取,而不是在按下时读取吗?

另外,如果它不可能或你不熟悉sfml,那么用很少或没有全局变量来模仿这样的最好方法是什么? (例如is_already_held),例如https://gamedev.stackexchange.com/questions/30826/action-button-only-true-once-per-press

我意识到这可能是唯一的方法(在更广泛的范围内声明一个变量),但我不愿意,因为我会不断地退出范围并尝试尽可能频繁地避开全局变量。

3 个答案:

答案 0 :(得分:7)

您可以使用sf::Window::setKeyRepeatEnabled禁用密钥重复:

window.setKeyRepeatEnabled(false);

创建窗口后调用一次(这就够了)。

文档为here


如果出于任何原因,您不想使用此函数,则可以使用布尔表来存储每个键的状态。这是一个伪代码,显示如何使表保持最新并集成您的“决策”代码。

// Init the table of state. true means down, false means up.
std::array<bool, sf::Keyboard::KeyCount> keyState;
keyState.fill(true);

// :
// :

// In the event loop:
if (event.type == sf::Event::KeyPressed)
{
    // If the key is UP and was not previously pressed:
    if (event.key.code == sf::Keyboard::Up && !keyState[event.key.code])
    {
        decision--;
        if (decision < 0)
            decision = CHARACTER_MAX - 1;
    }

    // Here comes the rest of your code and at the end of the if-body:

    // Update state of current key:
    keyState[event.key.code] = true;
}
else if (event.type == sf::Event::KeyReleased)
{
    // Update state of current key:
    keyState[event.key.code] = false;
}

第三种方法是使用第三方库,例如 Thor 。它仍在开发中,因此您可以期待作者的一些更改。 here你会找到关于行动的教程 - 也就是你所需要的。

答案 1 :(得分:2)

您可能希望使用sf::Event::KeyReleased来代替sf::Event::KeyPressed事件,只要键被“按住”,该事件就会继续运行,该事件的触发速度比键盘触发的持续时间要快得多。一个人“单”点击。

如果我跑步:

while(window.pollEvent(event)) {
   switch (event.type) {
     case sf::Event::KeyPressed:
       if(event.key.code == sf::Keyboard::Enter) {
         std::cout << "Enter key pressed!" << std::endl;
       }
     break;
   default:
     break;
   }
}

我会得到:

Enter key pressed!
Enter key pressed!
Enter key pressed!
Enter key pressed!
... etc

根据手指按住返回键的时间而定的任意次数(14、23、9、31等)。

如果我跑步:

while(window.pollEvent(event)) {
  switch (event.type) {
    case sf::Event::KeyReleased:
      if(event.key.code == sf::Keyboard::Enter) {
        std::cout << "Enter key pressed!" << std::endl;
      }
      break;
    default:
      break;
  }
}

我会得到:

Enter key pressed!

仅一次,基于返回键的单个释放。 :)

在某些情况下,您确实想使用sf::Event::KeyPressed事件,例如按住枪的“缩放”按钮,其范围只有在按下键时才缩放,或者按住“ Ctl”表示“文件编辑器等中的Ctl + alt + key“键组合。

答案 2 :(得分:1)

为避免在密钥关闭时重复触发事件,您可以使用sf::Event::KeyReleased代替sf::Event::KeyPressed。我认为这是你的目标。

如果没有,您将必须存储按钮状态。类是逻辑答案,因为它将状态与行为结合起来。