hgstuffinx hgstuffinx - 6 months ago 13
Javascript Question

Handling simultaneous KeyEvents in a Javascript Game

I'm working on an RPG in Javascript and am setting up controls for the main player, but I am having some issues with the keyEvent handling. This code controls player movement and animation. Where things go wrong, I believe, is that if the game registers a keydown while there is already another keydown, and then that first key goes up, the sprite pauses (the isMoving property basically stops movement and animation when it is false).

// For example:
// I hold W. Sprite begins moving up.
// While holding W, I begin to hold D. Sprite begins moving right.
// I release W. Sprite should keep going right, but pauses momentarily when the
// keyup is registered

var move = function(e) {

xavier.isMoving = true;

case 87: xavier.direction = 'up'; break; //W
case 65: xavier.direction = 'left'; break; //A
case 68: xavier.direction = 'right'; break; //D
case 83: xavier.direction = 'down'; break; //S
var wait = function(e) {
xavier.isMoving = false;
window.addEventListener("keydown", move, false);
window.addEventListener("keyup", wait, false);

Is there a better way to set up controls so that my game can handle multiple keys simultaneously?

Also, the sprite moves when mac command key is pushed. Not sure why. Thank you in advance for your help. This is my first question on StackOverflow. Hopefully it's OK.


You need to disassociate the key events from the animation or main game loop. THe keydown, keyup events are IO events and should not handle game logic, they can come in at any rate, you may have many between frames and applying logic on each is just a waste of processing, and worse if you have more logic involved the player may miss logic events because the key events have proceeded without the main loop processing the new positions. The same goes for the mouse and touch events, you should only record the events and handle them within the game.

// define keys and an array to keep key states
// global key log;
var keyState = [];
const KEY_UP = 38;
const KEY_DOWN = 40;
const KEY_LEFT = 37;
const KEY_RIGHT = 39;

// create a logging function
const keyEventLogger =  function (e) {  keyState[e.keyCode] = e.type == 'keydown';}
window.addEventListener("keydown", keyEventLogger);
window.addEventListener("keyup", keyEventLogger);

// define something to move
var player = {y : 100, x: 100};
const MOVE_SPEED = 2;

// in the main loop;
function update(timer) {
    if (keyState[KEY_UP]) {
        player.y -= MOVE_SPEED;
    if (keyState[KEY_DOWN]) {
        player.y += MOVE_SPEED;
    if (keyState[KEY_LEFT]) {
        player.x -= MOVE_SPEED;
    if (keyState[KEY_RIGHT]) {
        player.x += MOVE_SPEED;