Search code examples
javalwjglglfw

GLFW with LWJGL - glfwGetKey once


I'm developing a game with java and LWJGL3. But I don't understand how to fix my problem, I've tried to search on the internet but the information for LWJGL is minimal and I couldn't find anything for GLFW.

Let's say for example I have a menu with 4 buttons (new game, options, credits, exit) and a count variable to know which one is selected. Every time the up arrow key is pressed I want to subtract one from the select, to select the previous one, and the same for the down arrow key, but I want to add one.

The problem is the following: if in the frame 0 I press the arrow key the count variable is added but in the next frame the key is still pressed, so it is added again. I don't know how to fix this, I tried to changing GLFW_PRESS to GLFW_RELEASE, but I want the action to happen when the key was pressed.

if ((glfwGetKey(window, GLFW_KEY_UP) == GLFW_REPEAT) && select > 0) {
    button[select].toggleSelect();
    select--;
    button[select].toggleSelect();
}

if ((glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_REPEAT) && select < button.length) {
    button[select].toggleSelect();
    select++;
    button[select].toggleSelect();
}

I know that this code can throw an array index out of bounds exception


Solution

  • You should register a key callback:

    private GLFWKeyCallback keyCallback;
    
    // ...
    
    keyCallback = new GLFWKeyCallback() {
        @Override
        public void invoke(long window, int key, int scancode, int action, int mods) {
            if (action == GLFW_PRESS) {
                if (key == GLFW_KEY_UP && /*...*/) {
                    // ...
                }
                if (key == GLFW_KEY_DOWN && /*...*/) {
                    // ...
                }
            }
        }
    }
    glfwSetKeyCallback(window, keyCallback);
    

    The invoke() method will be called every time a key event is generated. The action parameter can take three values:

    • GLFW_PRESS when the key was just pressed
    • GLFW_REPEAT afterwards, when the key is still being pressed
    • GLFW_RELEASE when the key wast just released

    While glfwGetKey() returns only GLFW_PRESS or GLFW_RELEASE, the key callback only uses GLFW_PRESS the first time the key is being pressed and GLFW_REPEAT afterwards, allowing you to differentiate between the first frame during which the key is pressed and subsequent ones.