尽管每帧都调用一次,但如何只执行一次方法代码

时间:2016-09-24 22:56:30

标签: c++ events input triggers keyboard

我正在编写一个游戏,在我的InputHandler类中,我编写了一个getKeyState方法,该方法返回一个特定的键是否被按下(bool)。

在某些情况下,问题在于,无论我怎么努力,按下一个键总是需要“太久”,以至于我的getKeyState方法多次返回true,因为每个帧都会调用它。

当我需要执行一次特定操作时,我必须写下这样的内容:

int n = 0; // global variable

(...)

// --- inside a class method which is called every frame as well: ---

if (Input.getKeyState(key))
{
    n++;

    if (n == 1)
    {
        // specific behaviour
    }
}
else
{
    n = 0;
}

我现在的问题是:如何在InputHandler类中的方法中实现此目的。我不想每次都声明一个计数器变量,我需要一个“Key only pressed once”-method。我想打电话:

if (Input.isKeyPressedAndTriggerOnlyOncePls())

2 个答案:

答案 0 :(得分:1)

编辑:  你需要检查按键,然后检查按下键。

bool keyPressed = false;

bool InputHandler(){
   if(keyPresed == false){
      if( key is being pressed ){
         keyPressed = true;
         return true;
      }
   }
   else{
      if( key is not being pressed ){
         keyPressed = false;
      }
       return false;
   }
}

EDIT2: 如果你真的想让InputHandler()进行检查,你可以为每个调用者提供一个标志数组,并为每个调用者提供一个ID,然后如果调用了InputHandler(),则按下键并且ID的标志为false,返回true ,否则你返回false,但是你必须在每次按下键时重置所有标志。

所以前面的代码看起来像这样:

bool arrayReset = true;
bool pressUsed[Number of callers] = {0};

bool InputHandler(int id){
   if(key is being pressed){
      if( pressUsed[id] == false){
         pressUsed[id] = true;
         arrayReset = false;
         return true;
      }
   }
   else if( key is not being pressed && arrayReset == false){
         arrayReset = true;
         set pressUsed[] all elements to false;
   }

return false;
}

EDIT3: 如果您多次调用该方法但在同一循环中,则可以执行以下操作:

bool keyPressed = false;

bool InputHandler(){
   if(key is being pressed && keyPresed == false)
     return true;
}


bool InputHandlerWithChange(){
   if(keyPresed == false){
      if( key is being pressed ){
         keyPressed = true;
         return true;
      }
   }
   else{
      if( key is not being pressed ){
         keyPressed = false;
      }
       return false;
   }
}

每次需要检查是否按下某个键时,调用InputHandler()。在循环结束时或在需要检查按键的最后一个位置调用InputHandlerWithChange(),这样当按下键时所有调用者都将收到true,并且在键被按下之前将停止接收true。

答案 1 :(得分:0)

执行此操作的一种方法是使用静态数据成员创建父类。然后,您可以创建从该类继承的输入处理程序。

// Main parent class
class InputHandlerParent {
public:
    InputHandlerParent() {} ;
    virtual bool isKeyPressedAndTriggerOnlyOncePls()
    {
        return keypressed;
    }
    virtual void setKeyPressed()
    {
        keypressed = true ;
        std::cout << "YOU PRESSED THE KEY!" << std::endl;
    }
    virtual void unsetKeyPressed()
    {
        keypressed = false ;
        std::cout << "YOU RELEASED THE KEY!" << std::endl;
    }
protected:
    static bool keypressed ;
private:
};

// Now an example child class
class InputHandlerChild : public InputHandlerParent {
public:
    InputHandlerChild() :
        InputHandlerParent()
    {};
protected:
private:
};

// Define keypressed
bool InputHandlerParent::keypressed = false ;

所有继承子类共享keypressed变量,因此如果您执行以下操作:

#include <iostream>
int main()
{
    InputHandlerChild child1 ;
    InputHandlerChild child2 ;

    std::cout << "Child1 pressed: " << child1.isKeyPressedAndTriggerOnlyOncePls() << std::endl;
    std::cout << "Child2 pressed: " << child2.isKeyPressedAndTriggerOnlyOncePls() << std::endl;

    // Now set the key as pressed
    child1.setKeyPressed() ;

    std::cout << "Child1 pressed: " << child1.isKeyPressedAndTriggerOnlyOncePls() << std::endl;
    std::cout << "Child2 pressed: " << child2.isKeyPressedAndTriggerOnlyOncePls() << std::endl;

    // Unset the key ONLY if it was set for child2
    if (child2.isKeyPressedAndTriggerOnlyOncePls()) {
        child2.unsetKeyPressed() ;
    }

    std::cout << "Child1 pressed: " << child1.isKeyPressedAndTriggerOnlyOncePls() << std::endl;
    std::cout << "Child2 pressed: " << child2.isKeyPressedAndTriggerOnlyOncePls() << std::endl;

    return 0 ;
}

这给出了输出

Child1 pressed: 0
Child2 pressed: 0
YOU PRESSED THE KEY!
Child1 pressed: 1
Child2 pressed: 1
YOU RELEASED THE KEY!
Child1 pressed: 0
Child2 pressed: 0

所以即使我只为一个孩子按下它,每个人都知道它被按下了。基本上,只要按下该键,您就可以调用setKeyPressed()keypressed设置为true。然后,每当动作发生时取消设置密钥,您可以调用unsetKeyPressed()让每个人都知道密钥不再被按下。