jquerykeypress

move element with keypress (multiple)


Diagonal move not working and issue on left-longPress/right simultaneous

But on double keypress the ship goes crazy!

$(document).bind('keydown', function(e) {
    var box = $("#plane"),
        left = 37,
        up = 38,
        right = 39,
        down = 40

    if (e.keyCode == left) {
        box.animate({left: "-=5000"},3000);
    }
    if (e.keyCode == up) {
        box.animate({top: "-=5000"},3000);
    }
    if (e.keyCode == right) {
        box.animate({left:"+=5000"},3000);
    }
    if (e.keyCode == down) {
        box.animate({top: "+=5000"},3000);
    }
});
$(document).bind('keyup', function() {
    $('#plane').stop();
});

Solution

  • In game development it's best to create a wrapper around the keyboard.
    Such wrapper should implement the following:

    To fix the diagonal player movement, you can do it in wo ways, using an angle of rotation, or move the player diagonally by 1 / Math.sqrt(2) (approximately ~ 0.7071) distance. In the following example I'll use angles (in radians):

    const player = {
      el: document.querySelector("#player"),
      x: 100, y: 50,
      dirX: 0, dirY: 0,
      velX: 0, velY: 0,
      power: 2, angle: 0,
      move() {
        if (this.dirX || this.dirY) {
          this.angle = Math.atan2(this.dirY, this.dirX);
          this.velX = Math.cos(this.angle) * this.power;
          this.velY = Math.sin(this.angle) * this.power;
          this.x += this.velX;
          this.y += this.velY;
          this.dirX = this.dirY = 0; // Reset directions
        }
        this.el.style.translate = `${this.x}px ${this.y}px`;
        this.el.style.rotate = `${this.angle}rad`;
      }
    };
    
    const keyboard = {
      actions: new Map(Object.entries({
        ArrowLeft  () { player.dirX = -1; },
        ArrowRight () { player.dirX =  1; },
        ArrowUp    () { player.dirY = -1; },
        ArrowDown  () { player.dirY =  1; },
        // add more key actions here
      })),
      keys: new Set(),
      handle(evt) {
        if (evt.repeat || !this.actions.has(evt.key)) return;
        evt.preventDefault();
        this.keys[evt.type === "keydown" ? "add" : "delete"](evt.key);
      },
      callActions() {
        for (let key of this.keys) this.actions.get(key)();
      }
    };
    
    addEventListener("keydown", (evt) => keyboard.handle(evt));
    addEventListener("keyup", (evt) => keyboard.handle(evt));
    
    const engine = () => {
      keyboard.callActions();
      player.move();
      requestAnimationFrame(engine);
    };
    
    engine();
    #player{
      position: absolute;
      left: 0;  top: 0;
      width: 20px;  height: 20px;
      background: #0bf;  border-radius: 50%;
    }
    Click here to focus and use arrow keys to move:
    <div id="player">&rarr;</div>