19

Possible Duplicate:
JavaScript move delay and multiple keystrokes

I'm new and learning HTML5 canvas together with javascript. I've created an event to move an object left and right, and my problem is the delay whenever you hold the key or switch to another key. I know there's missing on my code below please help me. Thank you in advance.

c.addEventListener('keydown',this.check,true);
  function check(el) {
    var code = el.keyCode || el.which;
    if (code == 37 || code == 65){
    x -=1;
    }

    if (code == 39 || code == 68){
    x += 1;
    }

  el.preventDefault();
}
Community
  • 1
  • 1
user1441816
  • 859
  • 3
  • 12
  • 24

1 Answers1

60

Rather than trying to react directly to the keydown event, I'd suggest you use the keydown and keyup events to maintain a list of which keys are presently down. Then implement a "game loop" that checks every x milliseconds which keys are down and update the display accordingly.

var keyState = {};    
window.addEventListener('keydown',function(e){
    keyState[e.keyCode || e.which] = true;
},true);    
window.addEventListener('keyup',function(e){
    keyState[e.keyCode || e.which] = false;
},true);

x = 100;

function gameLoop() {
    if (keyState[37] || keyState[65]){
        x -= 1;
    }    
    if (keyState[39] || keyState[68]){
        x += 1;
    }

    // redraw/reposition your object here
    // also redraw/animate any objects not controlled by the user

    setTimeout(gameLoop, 10);
}    
gameLoop();

You'll notice that this lets you handle multiple keys at once, e.g., if the user presses the left and up arrows together, and the problem of delay between subsequent keydown events when a key is held down goes away since all you really care about is whether a keyup has occurred.

I realise you may not be implementing a game, but this "game loop" concept should work for you as shown in this very simple demo: http://jsfiddle.net/nnnnnn/gedk6/

nnnnnn
  • 147,572
  • 30
  • 200
  • 241
  • 1
    You're welcome. (Note that there are more complicated techniques that serious game-coders would use to control the speed of the game loop, but you can Google those if you're interested - this answer was intended as a simple intro to the game loop and key-state concepts to get you past your current problem.) – nnnnnn Sep 05 '12 at 02:15
  • 1
    @nnnnnn This code snippet turns to be the solution to a problem I'm having. Thanks for the code! However, is there any way I can detect a `keyup` (so that I can fire another function)? – AKG Jun 22 '13 at 11:15
  • 2
    @AKG - Well, the example I gave does already have a keyup handler, so you can add a call to your function there. Or just add a second keyup handler. – nnnnnn Jun 22 '13 at 11:55
  • @nnnnnn That's right, but what should I amend if I only want to capture that one moment the user releases the key? Right now, it loops `keyState[37]` (or any other key) being `false` upon release. Hope this makes sense. Thanks 8) – AKG Jun 22 '13 at 12:44
  • 2
    @AKG - I don't understand. The keyup handler is called at the one moment the user releases the key. As I said before, add your function call within the keyup handler, or add a second keyup handler, don't try to do it from the game loop function based on the `keyState` object. – nnnnnn Jun 22 '13 at 13:24
  • @nnnnn wow. That's a huge temporary logic lapse on my part. Haven't slept for a day! Thanks! – AKG Jun 22 '13 at 13:29