Skip to main content

Sluggish input response with long key presses

4 replies [Last post]
justin83
Offline
Joined: 2006-07-04

Hi all,

This isn't unique to Java3D, but I've noticed that key processing is slugglish when a key is held down. This is especially frustrating for games. I've noticed this both when I listen for a KeyEvent using the traditional KeyListener.keyPressed() method for 2D games and when using Behaviors with Java3D. With Java3D, I subclass Behavior, register a WakeupOnAWTEvent(KeyEvent.PRESSED), and process events from the Behavior.processStimulus() method.

When a key is held down, say when a player wants to keep moving forward, it takes about 1 second for the system to respond to the initial key press. After the initial delay, things proceed normally, but the delay is annoying for the user, especially if the user wants to change direction quickly. If I just "tap" the key, then key processing proceeds without delay.

Am I doing something wrong? Should I be processing the events differently for these long, continuous key presses? I've programmed before using DirectX, and you were able to manually "poll" the keyboard and doing this in the main game loop avoided this sluggish input problem (but of course programming with DirectX was generally otherwise a pain :-).

Thanks,

Justin

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
pepe
Offline
Joined: 2003-06-10

Hello.
Don't you get an initial keydown before pause?
If you use the system directly, you will get what you get when you press a key:
- an event for the initial keydown
- a pause (repetition delay)
- a succession of keydown events (at keyrepeat delay.)
Those two delays are OS based. Under windows you can see them within control panel/keyboard properties. In 'speed' tab, you have them two.

While it is right for a gui, this is not what you have to do for a game. You have to list pressed keys when you get a keydown, then for each and every behavior processStimulus() use that list instead of events, and clear each element of the list once you get their keyup event.

for a key event tracer webstart demo, please get there:
http://java.sun.com/docs/books/tutorial/uiswing/events/keylistener.html

justin83
Offline
Joined: 2006-07-04

Thanks for your reply.

I tried doing what you said, but I still get the delay. It seems that processStimulus() also suffers the pause as well. I use the map "keyDownEvents" mapping keyCodes to the keyEvents that generated them. When I receive a key pressed event, I store a mapping. I remove the mapping when that key is released. After enumerating all the wakeup criteria, I then enumerate and process the current list of key events stored in the map at the end of the processStimulus() method.

I guess I could subclass Canvas3D and override the preRender method and enumerate the list there. Or is there something else I am missing?

-Justin

justin83
Offline
Joined: 2006-07-04

It's fixed now. I simply added a third condition to my WakeupOnOr criterion:

WakeupCriterion [] conditions = new WakeupCriterion[3];
conditions[0] = new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED);
conditions[1] = new WakeupOnAWTEvent(KeyEvent.KEY_RELEASED);
conditions[2] = new WakeupOnElapsedTime(17); //called at 60 fps
action = new WakeupOr(conditions);

This way the processStimulus() method is called at least every 17ms. I first used a WakeupOnElapsedFrames(0) criterion, but this was undesirable since it was taxing the CPU too much when there were no key events in the list to process since it was being called every frame.

-Justin

pepe
Offline
Joined: 2003-06-10

Oh, yes, of course. I did not think about the constant update. If you do not have a constantly running render, just noting the key events can only act as it did.
Nevertheless, i would put the wakeupOnElapsedTime() condition if there are key pressed in the list. That way, the system will not render continuously if there are no keys pressed.