KeyMapper isn't working with the software renderer...

Started by AGP, November 01, 2011, 09:09:57 PM

Previous topic - Next topic

AGP

...even after I added the premusably redundant line this.addKeyListener(keyMapper). My game loop prints "polling" just before I poll the KeyMapper, but then the state is always RELEASED (with key code 0). Very bizarre. It's worth noting that the pre-game parts of my game are handled on a canvas that I remove from the frame when the game starts. But this.addKeyListener(keyMapper) is being called AFTER the call to remove the canvas.

EgonOlsen

...and you are using the constructor that takes the Component?


EgonOlsen

No idea. It works fine for me...here's the code for the KeyMapper. Maybe this helps to find the problem:


package com.threed.jpct.util;

import java.awt.event.*;
import java.awt.*;
import org.lwjgl.input.*;
import org.lwjgl.opengl.*;
import com.threed.jpct.FrameBuffer;

/**
* KeyMapper is convenience class to ease the different handling of the keyboard
* when using hard- or software rendering. It provides a uniform way to access
* the keyboard.
*/
public class KeyMapper implements KeyListener {

private int bufferSize = 10;

private KeyState[] keys;

private int[] awtKeyState;

private int keyCnt;

private int pollCnt;

private boolean lwjgl;

private Component comp = null;

private boolean created = false;

private int[] mapping = new int[] { Keyboard.KEY_NONE, KeyEvent.VK_UNDEFINED, 0, Keyboard.KEY_ESCAPE, KeyEvent.VK_ESCAPE, 0, Keyboard.KEY_1, KeyEvent.VK_1, 0, Keyboard.KEY_2, KeyEvent.VK_2, 0,
Keyboard.KEY_3, KeyEvent.VK_3, 0, Keyboard.KEY_4, KeyEvent.VK_4, 0, Keyboard.KEY_5, KeyEvent.VK_5, 0, Keyboard.KEY_6, KeyEvent.VK_6, 0, Keyboard.KEY_7, KeyEvent.VK_7, 0, Keyboard.KEY_8,
KeyEvent.VK_8, 0, Keyboard.KEY_9, KeyEvent.VK_9, 0, Keyboard.KEY_0, KeyEvent.VK_0, 0, Keyboard.KEY_MINUS, KeyEvent.VK_MINUS, 0, Keyboard.KEY_EQUALS, KeyEvent.VK_EQUALS, 0,
Keyboard.KEY_BACK, KeyEvent.VK_BACK_SPACE, 0, Keyboard.KEY_TAB, KeyEvent.VK_TAB, 0, Keyboard.KEY_Q, KeyEvent.VK_Q, 0, Keyboard.KEY_W, KeyEvent.VK_W, 0, Keyboard.KEY_E, KeyEvent.VK_E, 0,
Keyboard.KEY_R, KeyEvent.VK_R, 0, Keyboard.KEY_T, KeyEvent.VK_T, 0, Keyboard.KEY_Y, KeyEvent.VK_Y, 0, Keyboard.KEY_U, KeyEvent.VK_U, 0, Keyboard.KEY_I, KeyEvent.VK_I, 0, Keyboard.KEY_O,
KeyEvent.VK_O, 0, Keyboard.KEY_P, KeyEvent.VK_P, 0, Keyboard.KEY_LBRACKET, KeyEvent.VK_LEFT_PARENTHESIS, 0, Keyboard.KEY_RBRACKET, KeyEvent.VK_RIGHT_PARENTHESIS, 0, Keyboard.KEY_RETURN,
KeyEvent.VK_ENTER, 0, Keyboard.KEY_LCONTROL, KeyEvent.VK_CONTROL, 0, Keyboard.KEY_A, KeyEvent.VK_A, 0, Keyboard.KEY_S, KeyEvent.VK_S, 0, Keyboard.KEY_D, KeyEvent.VK_D, 0, Keyboard.KEY_F,
KeyEvent.VK_F, 0, Keyboard.KEY_G, KeyEvent.VK_G, 0, Keyboard.KEY_H, KeyEvent.VK_H, 0, Keyboard.KEY_J, KeyEvent.VK_J, 0, Keyboard.KEY_K, KeyEvent.VK_K, 0, Keyboard.KEY_L, KeyEvent.VK_L, 0,
Keyboard.KEY_SEMICOLON, KeyEvent.VK_SEMICOLON, 0, Keyboard.KEY_APOSTROPHE, KeyEvent.VK_COLON, 0, Keyboard.KEY_GRAVE, KeyEvent.VK_DEAD_GRAVE, 0, Keyboard.KEY_LSHIFT, KeyEvent.VK_SHIFT, 0,
Keyboard.KEY_BACKSLASH, KeyEvent.VK_BACK_SLASH, 0, Keyboard.KEY_Z, KeyEvent.VK_Z, 0, Keyboard.KEY_X, KeyEvent.VK_X, 0, Keyboard.KEY_C, KeyEvent.VK_C, 0, Keyboard.KEY_V, KeyEvent.VK_V, 0,
Keyboard.KEY_B, KeyEvent.VK_B, 0, Keyboard.KEY_N, KeyEvent.VK_N, 0, Keyboard.KEY_M, KeyEvent.VK_M, 0, Keyboard.KEY_COMMA, KeyEvent.VK_COMMA, 0, Keyboard.KEY_PERIOD, KeyEvent.VK_PERIOD,
0,
Keyboard.KEY_SLASH,
KeyEvent.VK_SLASH,
0,
Keyboard.KEY_RSHIFT,
KeyEvent.VK_SHIFT,
0,
Keyboard.KEY_MULTIPLY,
KeyEvent.VK_MULTIPLY,
0,
Keyboard.KEY_LMENU,
KeyEvent.VK_UNDEFINED,
0, // Ändern...
Keyboard.KEY_SPACE, KeyEvent.VK_SPACE, 0, Keyboard.KEY_CAPITAL, KeyEvent.VK_CAPS_LOCK, 0, Keyboard.KEY_F1, KeyEvent.VK_F1, 0, Keyboard.KEY_F2, KeyEvent.VK_F2, 0, Keyboard.KEY_F3,
KeyEvent.VK_F3, 0, Keyboard.KEY_F4, KeyEvent.VK_F4, 0, Keyboard.KEY_F5, KeyEvent.VK_F5, 0, Keyboard.KEY_F6, KeyEvent.VK_F6, 0, Keyboard.KEY_F7, KeyEvent.VK_F7, 0, Keyboard.KEY_F8,
KeyEvent.VK_F8, 0, Keyboard.KEY_F9, KeyEvent.VK_F9, 0, Keyboard.KEY_F10, KeyEvent.VK_F10, 0, Keyboard.KEY_NUMLOCK, KeyEvent.VK_NUM_LOCK, 0, Keyboard.KEY_SCROLL, KeyEvent.VK_SCROLL_LOCK,
0, Keyboard.KEY_NUMPAD7, KeyEvent.VK_NUMPAD7, 0, Keyboard.KEY_NUMPAD8, KeyEvent.VK_NUMPAD8, 0, Keyboard.KEY_NUMPAD9, KeyEvent.VK_NUMPAD9, 0, Keyboard.KEY_SUBTRACT, KeyEvent.VK_SUBTRACT,
0, Keyboard.KEY_NUMPAD4, KeyEvent.VK_NUMPAD4, 0, Keyboard.KEY_NUMPAD5, KeyEvent.VK_NUMPAD5, 0, Keyboard.KEY_NUMPAD6, KeyEvent.VK_NUMPAD6, 0, Keyboard.KEY_ADD, KeyEvent.VK_ADD, 0,
Keyboard.KEY_NUMPAD1, KeyEvent.VK_NUMPAD1, 0, Keyboard.KEY_NUMPAD2, KeyEvent.VK_NUMPAD2, 0, Keyboard.KEY_NUMPAD3, KeyEvent.VK_NUMPAD3, 0, Keyboard.KEY_NUMPAD0, KeyEvent.VK_NUMPAD0, 0,
Keyboard.KEY_DECIMAL, KeyEvent.VK_DECIMAL, 0, Keyboard.KEY_F11, KeyEvent.VK_F11, 0, Keyboard.KEY_F12, KeyEvent.VK_F12, 0, Keyboard.KEY_F13, KeyEvent.VK_F13, 0, Keyboard.KEY_F14,
KeyEvent.VK_F14, 0, Keyboard.KEY_F15, KeyEvent.VK_F15, 0, Keyboard.KEY_KANA, KeyEvent.VK_KANA, 0, Keyboard.KEY_CONVERT, KeyEvent.VK_CONVERT, 0, Keyboard.KEY_NOCONVERT,
KeyEvent.VK_NONCONVERT,
0,
Keyboard.KEY_YEN,
KeyEvent.VK_UNDEFINED,
0,// Ändern...
Keyboard.KEY_NUMPADEQUALS, KeyEvent.VK_EQUALS, 0, Keyboard.KEY_CIRCUMFLEX, KeyEvent.VK_CIRCUMFLEX, 0, Keyboard.KEY_AT, KeyEvent.VK_AT, 0, Keyboard.KEY_COLON, KeyEvent.VK_COLON, 0,
Keyboard.KEY_UNDERLINE, KeyEvent.VK_UNDERSCORE, 0, Keyboard.KEY_KANJI, KeyEvent.VK_KANJI, 0, Keyboard.KEY_STOP, KeyEvent.VK_STOP, 0,
Keyboard.KEY_AX,
KeyEvent.VK_UNDEFINED,
0, // Ändern...
Keyboard.KEY_UNLABELED,
KeyEvent.VK_UNDEFINED,
0, // Ändern...
Keyboard.KEY_NUMPADENTER, KeyEvent.VK_ENTER, 0, Keyboard.KEY_RCONTROL, KeyEvent.VK_CONTROL, 0, Keyboard.KEY_NUMPADCOMMA, KeyEvent.VK_COMMA, 0, Keyboard.KEY_DIVIDE, KeyEvent.VK_DIVIDE, 0,
Keyboard.KEY_SYSRQ,
KeyEvent.VK_UNDEFINED,
0, // Ändern...
Keyboard.KEY_RMENU, KeyEvent.VK_UNDEFINED, 0, Keyboard.KEY_PAUSE, KeyEvent.VK_PAUSE, 0, Keyboard.KEY_HOME, KeyEvent.VK_HOME, 0, Keyboard.KEY_UP, KeyEvent.VK_UP, 0, Keyboard.KEY_PRIOR,
KeyEvent.VK_PAGE_UP, 0, Keyboard.KEY_LEFT, KeyEvent.VK_LEFT, 0, Keyboard.KEY_RIGHT, KeyEvent.VK_RIGHT, 0, Keyboard.KEY_END, KeyEvent.VK_END, 0, Keyboard.KEY_DOWN, KeyEvent.VK_DOWN, 0,
Keyboard.KEY_NEXT, KeyEvent.VK_PAGE_DOWN, 0, Keyboard.KEY_INSERT, KeyEvent.VK_INSERT, 0, Keyboard.KEY_DELETE, KeyEvent.VK_DELETE, 0, Keyboard.KEY_LWIN, KeyEvent.VK_UNDEFINED, 0, // Ändern...
Keyboard.KEY_RWIN, KeyEvent.VK_UNDEFINED, 0, Keyboard.KEY_APPS, KeyEvent.VK_UNDEFINED, 0, Keyboard.KEY_POWER, KeyEvent.VK_UNDEFINED, 0, Keyboard.KEY_SLEEP, KeyEvent.VK_UNDEFINED, 0 };

/**
* Use this constructor to create a KeyMapper that works in combination with
* hardware rendering (i.e. that is using LWJGL's methods to access the
* keyboard).
*/
public KeyMapper() {
init(null);
}

/**
* Use this construtor to create a KeyMapper that works on an AWT/Swing
* component, which is usually your frame (or whatever) where the rendered
* output will be displayed onto. The KeyMapper will automatically register
* itself as a KeyListener of the component. To deregister, call destroy on
* this KeyMapper.
*
* @param comp
*            the component
*/
public KeyMapper(Component comp) {
init(comp);
}

/**
* Destroys the KeyMapper. This will free up used resources and will
* deregister the KeyMapper if required. It's mandatory to call this method
* before exiting your application or instantiating another KeyMapper.
*/
public void destroy() {
if (comp != null) {
comp.removeKeyListener(this);
awtKeyState = null;
} else {
synchronized (FrameBuffer.SYNCHRONIZER) {
if (Keyboard.isCreated()) {
Keyboard.destroy();
}
}
}
}

/**
* Poll the keyboard until no further KeyStates are available. In that case,
* KeyState.NONE will be returned.
*
* @return the KeyState (i.e. which key has been pressed/released)
*/
public synchronized KeyState poll() {
if (created) {
if (lwjgl) {
pollLWJGLKeys();
}

if (pollCnt != keyCnt && pollCnt < bufferSize) {
KeyState state = keys[pollCnt];
keys[pollCnt] = null;
pollCnt++;
return state;
} else {
pollCnt = 0;
keyCnt = 0;
return KeyState.NONE;
}
} else {
init(null);
return KeyState.NONE;
}
}

/**
* Has to be public, because KeyMapper implements KeyListener. No need to
* call this method directly.
*
* @param e
*            the KeyEvent
*/
public void keyTyped(KeyEvent e) {
}

/**
* Has to be public, because KeyMapper implements KeyListener. No need to
* call this method directly.
*
* @param e
*            the KeyEvent
*/
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code < awtKeyState.length) {
if (awtKeyState[code] != 1) {
awtKeyState[code] = 1;
processKey(e.getKeyCode(), e.getKeyChar(), true);
}
} else {
// Just do it in this case...if it ever happens!
processKey(e.getKeyCode(), e.getKeyChar(), true);
}
}

/**
* Has to be public, because KeyMapper implements KeyListener. No need to
* call this method directly.
*
* @param e
*            the KeyEvent
*/
public void keyReleased(KeyEvent e) {
int code = e.getKeyCode();
if (code < awtKeyState.length) {
if (awtKeyState[code] != 0) {
// Releasing a key that has never been pressed is impossible,
// but we are
// doing this check anyway...it won't hurt though.
awtKeyState[code] = 0;
processKey(e.getKeyCode(), e.getKeyChar(), false);
}
} else {
// Just do it in this case...if it ever happens!
processKey(e.getKeyCode(), e.getKeyChar(), false);
}

}

private void pollLWJGLKeys() {
synchronized (FrameBuffer.SYNCHRONIZER) {
if (Keyboard.isCreated()) {
// Keyboard.poll();
while (Keyboard.next()) {
int key = Keyboard.getEventKey();
char chr = Keyboard.getEventCharacter();
boolean state = Keyboard.getEventKeyState();
for (int i = 0; i < mapping.length; i = i + 3) {
if (mapping[i] == key) {
if (state && mapping[i + 2] != 1) {
processKey(mapping[i + 1], chr, true);
mapping[i + 2] = 1;
} else {
if (!state && mapping[i + 2] == 1) {
processKey(mapping[i + 1], chr, false);
mapping[i + 2] = 0;
}
}
}
}
}
}
}
}

private void init(Component comp) {
keys = new KeyState[bufferSize];
keyCnt = 0;
created = true;
if (comp != null) {
this.comp = comp;
awtKeyState = new int[0xFFFF];
comp.addKeyListener(this);
lwjgl = false;
} else {
lwjgl = true;
try {
synchronized (FrameBuffer.SYNCHRONIZER) {
if (!Keyboard.isCreated()) {
if (Display.isCreated()) {
Keyboard.create();
} else {
created = false;
}
}
}
} catch (Exception e) {
created = false;
}
}
}

private synchronized void processKey(int code, char chr, boolean pressed) {
while (keyCnt >= bufferSize) {
resizeBuffer();
}
keys[keyCnt] = new KeyState(code, chr, pressed);
keyCnt++;
}

private void resizeBuffer() {
KeyState[] newBuffer = new KeyState[bufferSize + 10];
System.arraycopy(keys, 0, newBuffer, 0, bufferSize);
bufferSize += 10;
keys = newBuffer;
}
}

AGP

It was, as I had suspected, a Java 7 issue. Adding frame.requestFocus() at the end of the constructor solved it for me. It was not a KeyMapper-specific issue, but rather a KeyListener one.

EgonOlsen

Makes sense to add it then to the KeyMapper, i guess... ???