0

I'm new to JavaScript and I'm having a problem using the "keypress" event; I'm currently making a small jumping script test, and both "keydown" and "keyup" events work, but not the "keypress" (I tried debugging using console.log() right after the event occurs but nothing shows up when pressing a key).

Here is my window.onload function (where I add my event listeners):

window.onload = function()
{
 canvas = document.getElementById('gameCanvas');
 ctx = canvas.getContext('2d');

 init();
 
 setInterval(function()
 {
  tick();
  render();
  
 }, 1000/FPS
 );
 
 // listeners
 window.addEventListener("keypress", function(evt)
 {
  if (evt.defaultPrevented)
  {
      return;
    }
    switch(evt.keyCode)
    {
     case 38:
      player.jump();
     break;
     default:
     return;
    }
 }
 );
 
 window.addEventListener("keydown", function(evt)
 {
  if (evt.defaultPrevented)
  {
      return;
    }
  switch(evt.keyCode)
  {
   case 37:
    player.moveLeft();
   break;
   case 39:
    player.moveRight();
   break;
   default:
   return;
  }
 }
 );
 
 window.addEventListener("keyup", function(evt)
 {
  if (evt.defaultPrevented)
  {
      return;
    }
  switch(evt.keyCode)
  {
   case 37:
   case 39:
    player.stop();
   break;
   default:
   return;
  }
 }
 );
}

Thanks for helping!

Fred vh
  • 45
  • 1
  • 6

2 Answers2

1

The keypress event concerns the actual input produced by pressing a certain key rather than the actual physical process of "pressing" the key.

I take it from your code that your interested in the arrow keys. Since arrow keys don't produce any type of character, they don't trigger the keypress event. The keydown and keyup events are the ones you'll want to use.

Also a final note: even for keys that trigger both the keydown and keypress events, the keyCode/which properties will usually be different between the two events, again because one concerns the actual key and the other concerns the produced input. Both keyCode and which are actually deprecated in favor of an abstracted key string property that removes this inconsistency between the different events.

Lennholm
  • 7,205
  • 1
  • 21
  • 30
  • It doesn't take much playing with key, keyCode, etc. to work out [*it's a mess*](http://unixpapa.com/js/key.html). :-( – RobG Jun 18 '17 at 22:34
1

Input for games

It is always best to isolate input from game play. Games generally use a regular loop to animate. The keyboard / mouse / touch and whatever else can be used as a controlling device is intermittent and have varying rates of fire between devices.

What you need to know is the current state of the input device for each frame of the game loop. With that all the input events should do is collect device state information.

Keyboard state listener

A keyboard state listener will only record the state of the keys you are interested in and/or wish to block default behaviour of. It can be turned on and off as needed.

Unfortunately not all browsers use the new code property, but not supporting the code property will mean at some point in the future your key handler will break when the depreciated keyCode property is dropped. So for now we must deal with the two systems. The code below maps the keyCode value to the code name.

const keyboard = (() => {
    var active = false;
    const keys = {
        ArrowLeft : false,  // only add keys you are interested in
        ArrowRight : false,
        Space : false,
        anyKey : false,
    };
    // map keyCodes to named code.
    const keyCodeMap = {
         k37 : "ArrowLeft",
         k39 : "ArrowRight",
         k32 : "Space",
    };
    function keyEvents (e) {
        var code = e.code;
        if (! code) { // if no support for code
            code = keyCodeMap["k" + e.keyCode];
        }  
        if (keys[code] !== undefined) {
            keys[code] = event.type === "keydown";
            e.preventDefault();
        }
        keys.anyKey = true;
    }
    const API = {
        start () {
            if (!active) {
                addEventListener("keyup", keyEvents);
                addEventListener("keydown", keyEvents);
                active = true;
            }
            return keys;
        },
        stop () {
            if (active) {
                removeEventListener("keyup", keyEvents);
                removeEventListener("keydown", keyEvents);
                active = false;
             }
        }
    }
    return API;
})();

To start and stop the keyboard

// Starting. Returns a keys state object. This is always the same object
const keys = keyboard.start(); // creates listeners

// stopping
keyboard.stop(); // removes listeners

To use in your main game loop

function mainLoop (time) {
    // check keyboard state and take action if needed
    // do rest of game
    requestAnimationFrame(mainLoop);
}

Only move while a key or keys is/are down

if (keys.ArrowRight) { moveRight() }
if (keys.ArrowLeft)  { moveLeft()  }

To perform an action only once

if (keys.Space) { // note holding down the key will repeat     
    keys.Space = false; // reset the key
    jumpAction();
}

To check if any key has been pressed

if (keys.anyKey) {
    // reset the key
    keys.anyKey = false;
    startGame();
}
Community
  • 1
  • 1
Blindman67
  • 51,134
  • 11
  • 73
  • 136