【问题标题】:Key Repetition in SFML 2.0SFML 2.0 中的关键重复
【发布时间】:2013-07-27 04:11:12
【问题描述】:

如果在 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

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

【问题讨论】:

  • while (window.pollEvent(event)); 注意; :这样做之后你只得到了最后一个事件。

标签: c++ events keyboard sfml


【解决方案1】:

您可以使用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 你会找到一个关于Action的教程——这正是你所需要的。

【讨论】:

    【解决方案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" 组合键

    【讨论】:

    • 注意:我更喜欢 setKeyRepeatEnabled() 或任何“按键”事件的原因是,几乎总是决定按键是完全不合逻辑的。如果您需要单击来触发事件而不是按住键,那么您一开始就不会按住键。这种方法很干净,如果您不是简单地敲击键,那么在大多数情况下您都不会使用它时,仍然可以让您充分利用“键持有”事件。
    • 有一些合法的用例可能需要两者兼得。例如,如果按住某个键会激活一种行为,而快速按下并重复释放会激活其他一些行为。
    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 2012-05-28
      • 1970-01-01
      • 2022-11-14
      • 1970-01-01
      • 2014-02-17
      • 1970-01-01
      • 2016-04-22
      • 1970-01-01
      • 2014-02-16
      相关资源
      最近更新 更多