skip to Main Content

Ive made a fairly simple movement script for a web based game I am making and I noticed that when a key is held down, it runs the movements once, waits a while, then starts moving continuously. I assume this is a thing that’s done by browsers to stop users from accidentally typing thousands of letters when holding a key down for too long, but is there any way to disable this?

This is a method used in my "Game" class which has all the functions needed for the game too run

movement(player) {
    let movements = {
        up: false,
        down: false,
        left: false,
        right: false,
        speed: 0,
        maxSpeed: 10,
        lastMove: null
    }

    function controls(e) {
        const key = e.key;
        if (key == "w") {
            e.preventDefault();
            movements.up = true;
        }
        if (key == "s") {
            e.preventDefault();
            movements.down = true;
        }
        if (key == "a") {
            e.preventDefault();
            movements.left = true;
        }
        if (key == "d") {
            e.preventDefault();
            movements.right = true;
        }
    }

    function movement(x) {
        let direction = null;

        if (movements.up) direction = "up";
        else if (movements.down) direction = "down";
        else if (movements.left) direction = "left";
        else if (movements.right) direction = "right";

        if (direction) {
            if (direction == "up" || direction == "down") {
                player.src = `${x.data.entities.player.image}${direction}.png`;
                player.style.top = `${parseInt(player.style.top) + (direction == "up" ? -1 : 1) * movements.speed}px`;
            } else {
                player.src = `${x.data.entities.player.image}${direction}.png`;
                player.style.left = `${parseInt(player.style.left) + (direction == "left" ? -1 : 1) * movements.speed}px`;
            }
            movements.lastMove = direction;
        }

        if (direction && movements.speed < movements.maxSpeed) {
            movements.speed++;
        }

        if (direction) {
            movements.up = false;
            movements.down = false;
            movements.left = false;
            movements.right = false;
        }

        requestAnimationFrame(() => movement(x));
    }


    requestAnimationFrame(() => movement(this));
    document.addEventListener("keydown", (e) => {
        controls(e);
    });
}

2

Answers


  1. A well known approach to minimize the dependency on OS and hardware is to handle yourself the keys state (up or down). Then you can just tell when key is down by looking at this dictionary object.

    var obj_down = {}
    var direction
    
    window.addEventListener("keydown", function(ev) {
      obj_down[ev.key] = true;
    })
    
    window.addEventListener("keyup", function(ev) {
      delete obj_down[ev.key];
    })
    
    
    function loop() {
      var keys = Object.keys(obj_down)
      output.innerText = "" + keys
    
      // for example:
      if (obj_down["ArrowDown"]) {
        direction = "down"
      }
      requestAnimationFrame(loop)
    }
    loop()
    Keys that are currently down: 
    <div id="output"></div>
    Login or Signup to reply.
  2. How to ignore keyboard auto repetition

    Settings for keyboard auto repeat functionality are managed by the O/S, and can’t be set in JavaScript from within a browser.

    Note auto repetition of keys that have been held down causes additional keydown events to be fired in the browser – with no keyup events between them.

    Hence to ignore repeated keys, disable keydown event handling at the end of the keydown handler, and re-enable it in a keyup handler added for that purpose, along the lines of:

    let repeating = false;  // boolean to ignore repeated keys
    document.addEventListener("keydown", (e) => {
        if(!repeating) {
             repeating = true;
             controls(e);  // existing keydown handler
        }
    });
    document.addEventListener("keyup", (e) => {
        repeating = false;
    });
    

    Concept demonstration:

    input.focus();
    
    function handler(e) {  // for `keydown` events
      output.textContent += e.key;
    }
    
    let repeating = false;
    document.addEventListener("keydown", (e) => {
        if(!repeating) {
             repeating = true;
             handler(e);
        }
    });
    document.addEventListener("keyup", (e) => {
        repeating = false;
    });
    Press and release keys,<br>
    or hold one down until it auto repeats:<br>
    <textarea id="input">
    
    </textarea>
    <p>
    Keys passed to the handler:
    <pre><code id="output"></code></pre>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search