Skip to content
Advertisement

Remove delay while pressing the second key LWJGL Java

I am running into a problem that I cannot find any solution for the moment even by searching on the internet.

I am currently working on a 2D game and I want my player to go on every direction and diagonally. For that reason I need to get two inputs from the keyboard, thing that I could code but now my problem is, when I press the second key, I have a slight delay where my player do not move. This is very annoying because the movement is not smooth at all when I am changing my direction. Here my class where I manage all the inputs. Thanks in advance for your help.

public class Input
{
    private static final Input INSTANCE = new Input();
    
    public final static float PI = (float) 3.141592;
    public final static float P2 = (float) (PI/2);
    
    private double x = Jeu.Isaac.getDeplacement().getHit().getEntity().getX();
    private double y = Jeu.Isaac.getDeplacement().getHit().getEntity().getY();
    private double a = Jeu.Isaac.getDeplacement().getA();
    
    private final int[] listeInput = {GLFW.GLFW_KEY_A, GLFW.GLFW_KEY_D, GLFW.GLFW_KEY_W, GLFW.GLFW_KEY_S,
            GLFW.GLFW_KEY_UP, GLFW.GLFW_KEY_DOWN, GLFW.GLFW_KEY_RIGHT, GLFW.GLFW_KEY_LEFT};
    
    private double speed = 5.85;

    public void drawBalle() 
    {
        Jeu.Isaac.getMunitions().drawBalle();
    }
    
    public DeplacerPersonnage getPlayerMove() {
        return Jeu.Isaac.getDeplacement();
    }
    
    private GLFWKeyCallback keyboard;
    
    private HashMap<Integer, Boolean> mappageTouches;
    
    private Input()
    {
        mappageTouches = new HashMap<Integer, Boolean>();
        
        for(int key:listeInput)
        {
            mappageTouches.put(key, false);
        }

        keyboard = new GLFWKeyCallback()
        {

            @Override
            public void invoke(long window, int key, int scancode, int action, int mods) 
            {
                if(action == GLFW.GLFW_RELEASE)
                {
                    mappageTouches.replace(key, false);
                }
                else if(action == GLFW.GLFW_PRESS)
                {
                    System.out.println("Pressed");
                    mappageTouches.replace(key, true);
                    getAWSDkeys();
                    getShotsKeys();
                }
                else
                {
                    System.out.println("hold");
                    getAWSDkeys();
                    getShotsKeys();
                }
            }
            
        };
    }
    
    
    public void getAWSDkeys()
    {
        for(Integer key:listeInput)
        {
            if(mappageTouches.get(key))
            {
                switch(key)
                {
                    case GLFW.GLFW_KEY_A:
                        a = PI;
                        if(!Jeu.Isaac.getDeplacement().getHit().isQCollision()) x -= speed;
                        Jeu.Isaac.getDeplacement().update(x, y, a);
                        Jeu.Isaac.getDeplacement().drawPlayer();
                        break;
                    case GLFW.GLFW_KEY_D:
                        a = 0;
                        if(!Jeu.Isaac.getDeplacement().getHit().isDCollision()) x += speed;
                        Jeu.Isaac.getDeplacement().update(x, y, a);
                        Jeu.Isaac.getDeplacement().drawPlayer();
                        break;
                    case GLFW.GLFW_KEY_W:
                        a = PI/2;
                        if(!Jeu.Isaac.getDeplacement().getHit().isZCollision()) y += speed;
                        Jeu.Isaac.getDeplacement().update(x, y, a);
                        Jeu.Isaac.getDeplacement().drawPlayer();
                        break;
                    case GLFW.GLFW_KEY_S:
                        a = 3*(PI/2);
                        if(!Jeu.Isaac.getDeplacement().getHit().isSCollision()) y -= speed;
                        Jeu.Isaac.getDeplacement().update(x, y, a);
                        Jeu.Isaac.getDeplacement().drawPlayer();
                        break;
                }
            }
        }

    }
    
    public void getShotsKeys()
    {
        for(Integer key:listeInput)
        {
            if(mappageTouches.get(key))
            {
                switch(key)
                {
                    case GLFW.GLFW_KEY_UP:
                        Jeu.Isaac.getMunitions().addBalle(new Balle(1, 1, Jeu.Isaac.getDeplacement().getHit().getEntity().getX(), Jeu.Isaac.getDeplacement().getHit().getEntity().getY(), 3));
                        break;
                    case GLFW.GLFW_KEY_DOWN:
                        Jeu.Isaac.getMunitions().addBalle(new Balle(1, 1, Jeu.Isaac.getDeplacement().getHit().getEntity().getX(), Jeu.Isaac.getDeplacement().getHit().getEntity().getY(), 4));
                        break;
                    case GLFW.GLFW_KEY_RIGHT:
                        Jeu.Isaac.getMunitions().addBalle(new Balle(1, 1, Jeu.Isaac.getDeplacement().getHit().getEntity().getX(), Jeu.Isaac.getDeplacement().getHit().getEntity().getY(), 2));
                        break;
                    case GLFW.GLFW_KEY_LEFT:
                        Jeu.Isaac.getMunitions().addBalle(new Balle(1, 1, Jeu.Isaac.getDeplacement().getHit().getEntity().getX(), Jeu.Isaac.getDeplacement().getHit().getEntity().getY(), 1));
                        break;
                }
            }
        }
        
    }
    
    public static Input getInstance()
    {
        return INSTANCE;
    }

    public void init(long window)
    {
        glfwSetKeyCallback(window, keyboard);
    }
    
}

Advertisement

Answer

The problem is that your input handling logic, like incrementing your x variable via x += speed; (in getAWSDkeys()) is only performed when the OS sends window event messages for your keyboard. That only happens for KEY_DOWN, KEY_UP and KEY_REPEAT events. And, yes, there is a delay between a KEY_DOWN and a KEY_REPEAT event when you press and hold the same key.

In order to fix that, you just have to move your game logic (like the aforementioned increment/decrement of the x or y variable) outside of the key event handler.

Normally, you have a game loop for that, which also calls glfwPollEvents() (or glfwWaitEvents() if you decoupled your input/window event handling from rendering).

So, your keyboard event handler function should only set some boolean flag for every possible key indicating that this key is now down/pressed or up/released. And in your game/input loop, you just query the state of your boolean flags and act accordingly by doing the x/y increment/decrement there.

Instead of storing your own boolean flags for all keys whether they are down/up, you can also use the glfwGetKey() function. Note, though, that this function does not query the current key state, but returns cached key state (cached intside of GLFW) which GLFW sets/remembers internally when you call glfwPollEvents()/glfwWaitEvents(). See: https://www.glfw.org/docs/3.3/input_guide.html#input_key

This function only returns cached key event state. It does not poll the system for the current physical state of the key.

In short: The problem is that your game logic is inside of the window event message callback (which is called by glfwPollEvents/glfwWaitEvents when there are keyboard events sent by the OS to your process/game). You must decouple the handling of input events from the actual game logic.

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement