GWT – Prevent Key Repeat Delays


The Problem

Have you ever noticed that short delay between holding down a key and the second letter appearing? This is a feature to prevent users from accidentally typing 2 letters when they press a key a little longer than usual. While this behavior is desirable in everyday browser and text-processing situations, it is totally wrong from a gaming point of view as one would prefer instantaneous key handling.

Imagine the following: you want your character to move to the right. So you would press and hold down the right cursor key. After taking one step the key-delay kicks in and waits roughly 300-400ms (Operating System dependent) before sending the next key event and moving the character further on.

This behavior results in a less fluent game-play and should be somehow coped with. Since key-press delays are an OS dependent setting there is no real way to adjust the value or turning it off without going into low-level coding (!=GWT). I managed to create a small workaround for the Zulu game which you may find interesting if you come across similar problems.

Be aware that key handling is implemented very differently in each browser!

The Implementation

My Controls class implements KeyPressHandler and KeyUpHandler thus it is always informed of keys which are being pressed and released. Once a key is pressed (eg: Right Cursor Key) a Timer class re-dispatches the event to the KeyPressHandler until the Key-Released Event is called or the natural Keyboard Events arrive (after the REPEAT_MS delay).

Listing A show an example:

public class Controls implements KeyPressHandler, KeyUpHandler {

  private KeyPressEvent lastEvent;
  private static final long REPEAT_MS = 150;

  public Controls() {
    this.activeKey = null;
    this.t.scheduleRepeating(REPEAT_MS);
  }

  private final Timer t = new Timer() {
    public void run() {
      if(lastEvent != null)
        // Redispatch event
        onKeyPress(lastEvent);
    }
  };

  @Override
  public void onKeyPress(final KeyPressEvent event) {
      // Remember event until key release
      lastEvent = event;
    // Move Character, attack, etc.
  }

  @Override
  public void onKeyUp(final KeyUpEvent event) {
    // Terminate all active key events
    lastEvent = null;
  }
}

While this GWT Key Repeat Delay workaround does the job pretty well, it is neither elegant nor efficient and has some nasty browser dependent caveats. Opera (10.62) fires a Key-Release Event after every KeyPressEvent even if the key is being held down which results in constant toggling of lastEvent. And Google’s own Chromium browser has massive problems with handling KeyEvents from cursor keys.

If you have other(better) solutions to the repeat delay problem in GWT, don’t hesitate to leave a comment.

Cheers!

-Sebastian

Dieser Beitrag wurde unter Coding, Zulu abgelegt und mit , , , verschlagwortet. Setze ein Lesezeichen auf den Permalink.

Hinterlasse eine Antwort