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

How to execute method code only once although called every frame

本文关键字:一次 调用 代码 方法 执行      更新时间:2023-10-16

我正在编程一个游戏,在我的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类中的方法中实现这一点。我不想每次都声明一个计数器变量,我需要一个"键只按一次"的方法。我想调用:

if (Input.isKeyPressedAndTriggerOnlyOncePls())

编辑:您需要检查是否按下键,然后再检查是否按下键。

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()被调用,key被按下并且ID的标志为假你返回真,否则你返回假,但是你必须在每次key未按下时重置所有标志。

所以前面的代码看起来像这样:
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,直到键被取消。

这样做的一种方法是用静态数据成员创建父类。然后,您可以创建从该类继承的输入处理程序。

// 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(),让每个人都知道该键不再按下。