Hot questions for Using Lightweight Java Game Library in keyboard

Question:

I have this game where I use the standard WASD keys as input.

Though not all the keyboards have a QWERTY layout. For instance, when I use an AZERTY keyboard, the WASD is a bit hard to use with the left hand.

I would like that no matter his keyboard the layout, by default the player puts his left hand at the same place.

I've read that it is possible to do this using a mechanism called keyboard scanning that I should perform at the first launch of the game.

So how to perform such a keyboard scanning with LWJGL (preferably with version 3)? Is it possible at all?

Note: I've developed a user-mapping system. Here I'm really speaking about the best default mapping when the player starts the game for the first time.


Answer:

You should not need to do any keyboard scanning if you use the glfwGetKey or glfwSetKeyCallback functions to receive input. Their documentation states

The key functions deal with physical keys, with layout independent key tokens named after their values in the standard US keyboard layout

If you need the actual character that was pressed, you can use glfwSetCharCallback.

Question:

I am making a class in my game engine were it will check for key inputs and I have all the keys set up in an enum where the I will select the ordinal int value from the list when I need it and it looks like it works, no warnings no errors and it starts however, when I try to check for the input in my main it crashes for some reason. Could someone please help me.

From my main class:

private void OnGameUpdate()
{
    KeyManager key = new KeyManager();

    if(key.KeyPressed(Keys.KEY_W))
    {
        JOptionPane.showMessageDialog(null, "Hello, it works!", "Test", JFrame.ERROR);
    }
}

Key Manager class:

public class KeyManager 
{
    private int CurrentKey;

    public enum Keys
    {
        KEY_0,
        KEY_1,
        KEY_2,
        //[...]all the other keys...
        KEY_Y,
        KEY_YEN,
        KEY_Z,
        KEYBOARD_SIZE
    }

    public boolean KeyPressed(Keys key)
    {
        this.CurrentKey = key.ordinal();
        return Keyboard.isKeyDown(CurrentKey);
    }

}

Answer:

when calling

Keyboard.isKeyDown(CurrentKey);

you're using the enum CurrentKey - but when you use enum.ordinal() you don't get the int-value that represents the key...

you must map your keys to the enum, because when you run your code:

Keys.KEY_0.ordinal() = 0; //what comes out

but you want

Keys.Key_0.ordinal() = 11; //what would be expected

one way to do this is to create a numbered enum:

public enum Keys
{
    KEY_0 (11),
    KEY_1 (2),
    //and so on

    KEY_xy(4711);

    int id;
    Keys(int id){
        this.id = id
    }

    @override
    int ordinal(){
        return id;
    }
}

i must confess i'm writing that enum from out of my head, so maybe there are minor typing errors on it...

Question:

In a LWJGL game I'm making I have 3 threads - one for graphics, one for processing/physics and one to provide world access and deal with multiplayer connections. The issue I'm having is that when I call Keyboard.isKeyDown() in the physics thread I have to hold it down for sometimes half a second or so before anything happens. This isn't because the thread is running slowly - it's the only thing in the loop at the moment, and a println call shows that it's updating. I'm wondering if this has something to do with the fact that the OpenGL context exists in the graphics thread and I'm calling keyboard calls from the physics thread? If I do the check in the graphics thread it works fine, but taking inputs there and sending them to the other thread would somewhat defy the point of having separate threads.

My keyboard check currently looks like this:

boolean escPressed = false;
private void process(){
    if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)){
        if(!escPressed){
            escPressed = true;
            GameStateManager.pauseUnpause();
        }
    }
    else{
        escPressed = false;
    }
}

My thread setup is simply this

public class Client {

    public static GraphicsThread graphics;
    public static PhysicsThread physics;
    public static ConnectionThread server;

    public static void main(String[] args) {
        GameStateManager.setState(GameStateManager.EnumState.MENU);
        graphics = new GraphicsThread();
        physics = new PhysicsThread();
        server = new ConnectionThread();


        physics.start();
        graphics.start();
        server.start();
    }

}

So can anyone tell me why there is a delay when calling the method from a different thread?

Update I did a quick test, and it any calls to Keyboard just seem to take a very long time to complete.

while(true){
    start = System.currentTimeMillis();
    Keyboard.isKeyDown(Keyboard.KEY_ESCAPE);
    end = System.currentTimeMillis();
    System.out.println(end-start);
}

Running that test showed results as high as 1100ms, which is ridiculously high. When running in the graphics thread it completes in less than a millisecond and prints 0. Not sure what's happening here.


Answer:

LWJGL 2 or 3? Shouldnt really matter..

though, as far as I know there shouldnt be a problem with calling this method on other Threads, although Calling it on the Thread where the OpenGL context is bound to is a good idea anyways.

For my setup I have one Thread dedicated to all OpenGL context related stuff. (E.g. openGL calls only). So in your case, Il would check for the keyPressed state in the graphics Thread, which passes a hint to the Physics Thread which does all the heavylifting (if there is any). Though details are up to you of course.

I hope this helps you

Edit: I came across this post when dealing with this problem as well, basically its not possible because of choice of design by LWJGL. You can manually separate it by hinting (as described above), or keep track of the state of every input device (updated in the graphics thread) which you check on from other Threads instead of using the Keyboards class.