Input event callback

Hello,

I have a probleme in my code can you help me please ?
I’m trying to write a C++ Game engine so far i’m stuck on input handling.

I got the following problem : when I press a key once it will not increment once my dummy variable but by like 300 or 400 depend on each run (on the game loop)
Whereas I have Update my x variable from the key_callback() it will indeed increment once

It seems that by the loop is running faster than the input event.

Here my code

// engine.cpp

    void Engine::Run()
    {
        if( Initialize() )
        {
            int x = 0;
            while( running )
            {
                wnd.PumpEvents();

                bool leftIsPressed = wnd.kbd.KeyIsPressed( GLFW_KEY_LEFT );
                if( leftIsPressed )
                {
                    ++x;
                    std::cout << "x -> " << x << std::endl;
                }

                wnd.SwapBuffer();
                
            }
        }
    }
// window.cpp

    void Window::key_callback( GLFWwindow* window,int key,int scancode,int action,int mods )
    {
        // Retrieve the Window instance from the user pointer
        Window* instance = static_cast<Window*>( glfwGetWindowUserPointer( window ) );

        switch( key )
        {
        case GLFW_KEY_LEFT:
            if( action == GLFW_PRESS /*|| action == GLFW_REPEAT*/ )
            {
                instance->kbd.SetKey( GLFW_KEY_LEFT,true );
            }
            else if( action == GLFW_RELEASE )
            {
                instance->kbd.SetKey( GLFW_KEY_LEFT,false );
                //std::cout << "Left is released!" << std::endl;
            }

            break;
        }
    }
// keyboard.cpp

   bool Keyboard::KeyIsPressed( int key )
    {
        return keyStates[key];
    }

    void Keyboard::SetKey( int key,bool state )
    {
        keyStates[key] = state;
    }

Thank you !

when I press a key once it will not increment once my dummy variable but by like 300 or 400 depend on each run (on the game loop)
Whereas I have Update my x variable from the key_callback() it will indeed increment once

Yes, this is what your code is written to do.

When keyStates[GLFW_KEY_LEFT] is set to true when GLFW_KEY_LEFT is pressed, and then potentially many frames later it is set to false when released. Your framerate is likely many times faster than you can press and release a key.

It only increments once if you update it in the callback because the callback only receives GLFW_PRESS when a key is initially pressed.

It seems that by the loop is running faster than the input event.

From the looks your wnd.PumpEvents(); likely calls glfwPollEvents(); every frame. However your fingers are slower than the framerate.

You could take a look at running the tests/events.c test code to understand how events work.

Thank you for the answer

I ran the event.c test code and this is exactly the behavior I want

  • PRESS KEY return ONCE “00000001 to 1 at 0.748: Key 0x0107 (LEFT) Scancode 0x014b (with no mods) was pressed”
  • RELEASE KEY return ONCE 00000002 to 1 at 0.795: Key 0x0107 (LEFT) Scancode 0x014b (with no mods) was released

But I need this to perform using my C++ style

Yes it runs every frame glfwPollEvents() shouldn’t be ? The doc mentions that glfwPollEvents() should be used for games (continuous frame processing)

Now with my actual code I’m afraid that when I will press the [GLFW_KEY_LEFT] my main entity will move to far from the left … (as the loope increment each x by 400 or 600…)
What I would like is to controle the increment
So If I press once it should increment by 1 only

Or maybe there is something that I’m missing and I’m sorry for my lack of understanding.
Thank you very appreciating

Yes you should run it every frame.

Now with my actual code I’m afraid that when I will press the [GLFW_KEY_LEFT] my main entity will move to far from the left … (as the loope increment each x by 400 or 600…)
What I would like is to controle the increment
So If I press once it should increment by 1 only

If you want the value to increment only once when the key is pressed you should increment it in the callback, or you need to reset the key states every frame.

static bool leftIsHeldDown = false; // static or member of your class as we need to remember the state
bool leftIsPressed = wnd.kbd.KeyIsPressed( GLFW_KEY_LEFT );
if( leftIsPressed  && !leftIsHeldDown )
{
    // only increment if left is *just* pressed and not held down
    ++x;
}
leftIsHeldDown = leftIsPressed; // set held state