4

如果在 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::events,我可以在第一次按下而不是按下时读取吗?

此外,如果它不可能或者您不熟悉 sfml,那么在很少或没有全球化变量的情况下模拟这种情况的最佳方法是什么?(例如is_already_held),例如https://gamedev.stackexchange.com/questions/30826/action-button-only-true-once-per-press

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

4

3 回答 3

8

您可以使用以下命令禁用键重复sf::Window::setKeyRepeatEnabled

window.setKeyRepeatEnabled(false);

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

文档在这里


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

// 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。它仍在开发中,因此您可以期待作者的一些更改。在这里,您将找到有关Action的教程——这正是您所需要的。

于 2013-07-27T08:51:55.420 回答
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”组合键在文件编辑器等中

于 2019-01-29T20:31:44.367 回答
1

为避免按键按下时重复触发事件,您可以使用sf::Event::KeyReleased代替sf::Event::KeyPressed. 我假设这是你的目标。

如果没有,您将不得不存储按钮状态。类是合乎逻辑的答案,因为它结合了状态和行为。

于 2013-07-26T20:31:37.470 回答