1

Im creating a small game in javascript that requires multiple keys to be pressed at once for an avatars movement.

To recognize multiple key presses I'm using "Braden Best"s answer to the question JavaScript multiple keys pressed at once which works well except for the fact that the document doesn't seem to multitask keyup events. For example if I want to press the up arrow key followed by the left arrow key then release the left arrow key the avatar would stop completely.

Here is an example code: https://Jsfiddle.net/552gc9dh/1/

var c = document.getElementById("canv");
var canv = c.getContext("2d");
console.log("test");

var map = {};
var playerlist = [];

function player(width, height, x, y, color, speedx, speedy) {
    this.width = width;
    this.height = height;
    this.x = x;
    this.y = y;
    this.color = color;
    this.speedx = speedx;
    this.speedy = speedy;
    playerlist.push(this);
}
var player1 = new player(50, 50, 0, 0, "red", 2, 2);
console.log(playerlist[0]);

function gravity(playerY) {


}

function createplayerlistener(name, key1, key2, key3, key4) {
    onkeydown = onkeyup = function(e) {
        e = e || event;
        map[e.keyCode] = e.type == 'keydown';
        if (name.x + name.speedx < c.width - name.width) {
            if (map[key1]) {
                name.x += name.speedx;
            }
        }
        if (name.x + name.speedx > 0) {

            if (map[key2]) {
                name.x -= name.speedx;
            }
        }
        if (name.y + name.speedy < c.height - name.height) {
            if (map[key3]) {
                name.y += name.speedy;
            }
        }
        if (name.y + name.speedy > 0) {
            if (map[key4]) {
                name.y -= name.speedy;
            }
        }

    }
}
createplayerlistener(player1, 39, 37, 40, 38);


setInterval(function() {

    canv.clearRect(0, 0, c.width, c.height);
    for (var i = 0; i <= playerlist.length - 1; i++) {
        canv.fillStyle = playerlist[i].color; // iterates through players and draws them
        canv.fillRect(playerlist[i].x, playerlist[i].y, playerlist[i].width, playerlist[i].height);
    }
}, 10); 
Seth McClaine
  • 9,142
  • 6
  • 38
  • 64
  • I'm not sure if I understand the issue... If I hold right and down, it moves diagonally, releasing the down arrow changes the path to continue to the right, isn't that the expected behavior? Never mind I see it now, seems inconsistent... – Seth McClaine Apr 14 '18 at 04:25
  • 1
    @Seth McClaine It depends on the order that you press the keys.If you press right then down and release the down arrow it will stop moving but if you press down then right and release the down key it will continue moving. – SynataxError Apr 14 '18 at 04:30

1 Answers1

0

This answer is more of a strategy...

I would set variables for directions and update them on keyDown and keyUp

Sudo Code

const North = false;
const West = false;
const South = false;
const East = false;

keyUp = keyDown = (keyType) {
  switch(keyType) {
    case 'up':
      North = !North;
      break;
    case 'right':
      East = !East;
      break;
    case 'down':
      South = !South;
      break;
    case 'left':
      West = !West;
      break;
  };
} 

setInterval({
  if(North) //move up

  if(South) //move down

  if(East) //Move right

  if(West) //Move left

}, 10);

This should maintain the current movement until you receive a command to cancel it. It will also allow up and down or right and left to counter each other if a user presses both.

Hopefully this helps!


Addition

Likely a more performant option would actually be to create a setInteval on keydown for a specific direction and remove it on keyUp, that way if the player is not interacting you are not running extra cycles ever 1/100 of a second

directions = {
  up: null,
  right: null,
  down: null,
  left: null
}

const startInterval = (keyType) => {
  direction[keyType] = setInteval(()=> move(keyType);
}
const endInterval = (keyType) => {
  clearInterval( direction[keyType]);
  direction[keyType] = null;
}
const keyUp = keyDown = (keyType) {
  if(direction[keyType] === null) {
    startInteval(keyType);
  } else { 
    endInterval(keyType);
  }
} 
Seth McClaine
  • 9,142
  • 6
  • 38
  • 64