-
Notifications
You must be signed in to change notification settings - Fork 148
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
KeyPressedPreferNative: More performat key input #829
base: master
Are you sure you want to change the base?
KeyPressedPreferNative: More performat key input #829
Conversation
e32e17a
to
49b4939
Compare
On windows, `Gdx.input.isKeyPressed` uses lwjgl's event system for fetching key inputs. This event-based system sometimes lags due to OS issues, so beatoraja had problem getting key state ASAP. When pressing multiple keys, some keys were registered later than other keys. This commit fixes the issue by utilizing Windows's `GetAsyncKeyState` function for fetching current keyboard state itself. Note that this function will poll key state regardless of whether the window is focused or not, so this could be documented. Reference: previous libgdx input polling system (from LWJGL2) https://github.com/LWJGL/lwjgl/blob/master/src/java/org/lwjgl/opengl/WindowsKeyboard.java
49b4939
to
8fc25ce
Compare
2481613
to
0bef0f0
Compare
Fix) beatoraja now only accept keys when the window is focused.
|
…lay.isActive() Display.isActive() requires a global lock on the display object, so it frequently stalls, resulting in less-than-optimal gaming experience. To make things lock-free, we again use JNA to implement `Display.isActive()` ourselves. Note that this code is coded for lwjgl2 backend the beatoraja currently uses. To maximize modularity, All input-specific code are confined in KeyPressedPreferNative class only.
Alt+F4 should kill the application.
I had noticed this issue before, which led me to write this project https://github.com/Merrg1n/beatoraja-ime-fix. After reading the source code, I found that libGDX handles keyboard input events tied to the game loop. This means the actual keyboard polling rate is bound to the game's frame rate. However, the |
Polling happens on a separate thread, so polling rate is much faster than the display refresh rate. Separate consideration is required for macOS/Linux. Every windows-specific aspects are enclosed on the |
Let me add some implementation details about LibGDX. Even though it appears that keyboard events are polled by another thread in the game, this is actually how it works. In LibGDX 1.9.9 (the version actually used in this repository), public boolean isKeyPressed (int key) {
if (!Keyboard.isCreated()) return false;
if (key == Input.Keys.ANY_KEY)
return pressedKeys > 0;
else
return Keyboard.isKeyDown(getLwjglKeyCode(key));
} This method actually calls public static boolean isKeyDown(int key) {
synchronized(OpenGLPackageAccess.global_lock) {
if (!created) {
throw new IllegalStateException("Keyboard must be created before you can query key state");
} else {
return keyDownBuffer.get(key) != 0;
}
}
} So next, we should focus on where the public static void poll() {
synchronized(OpenGLPackageAccess.global_lock) {
if (!created) {
throw new IllegalStateException("Keyboard must be created before you can poll the device");
} else {
implementation.pollKeyboard(keyDownBuffer);
read();
}
}
} It seems like it should work correctly, but the void mainLoop () {
// ...
graphics.lastTime = System.nanoTime();
boolean wasActive = true;
while (running) {
Display.processMessages();
// ...
}
}
|
Wow, awesome description :) I haven't noticed that behavior, but it seems very plausible. Probably I'll need to test it too! My PR could also help mitigate that, as my code doesn't rely on the lwjgl's event loop system. Minor corrections: On
So left and right shift keys are handled with |
Calling `Gdx.input.isKeyPressed` acquires lock of global some opengl mutex, so it takes quite a considerable amount of time. Filter out excessive calls with GetAsyncKeyState.
lwjgl already has implemented multiple JNIs for Windows APIs we need. Since JNI is much faster than JNA, with a help of various reflection help we use those native methods instead of maintaining our own c++/java JNI build native systems. - Corollary: removed JNA dependencies
OK everything else is quite optimized, and if I replace the polling thread's Example implementation. Thread polling = new Thread(() -> {
for (;;) {
input.poll();
Thread.yield();
}
}); |
On windows,
Gdx.input.isKeyPressed
uses lwjgl's event system for fetching key inputs. This event-based system sometimes lags due to OS issues, so beatoraja had problem getting key state ASAP. When pressing multiple keys, some keys were registered later than other keys.This commit fixes the issue by utilizing Windows's
GetAsyncKeyState
function for fetching current keyboard state itself.Reference: previous libgdx input polling system (from LWJGL2)
Additional library:
This adds jna to the dependencies. Whether the code works on mac/linux is not yet tested. Testing is required.
https://github.com/LWJGL/lwjgl/blob/master/src/java/org/lwjgl/opengl/WindowsKeyboard.java