0

Today I'm wondering how I could detect multiple key actions at once. For example, in this code example, I want to be able to press 2 arrow keys at once so that the ball could move diagonally.

Here's the code:

    <!DOCTYPE html>
  <html>
  <head>
      <title>Mousemove</title>
  </head>

  <body>

      <script src="https://code.jquery.com/jquery-2.1.0.js"></script>
<canvas id="canvas" width="500" height="500"></canvas>
      <script>

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var width = canvas.width;
var height = canvas.height;

var circle = function (x, y, radius, fillCircle) {
  ctx.beginPath();
  ctx.arc(x, y, radius, 0, Math.PI * 2, false);
  if (fillCircle) {
    ctx.fill();
  } else {
    ctx.stroke();
  }
};

// The Ball constructor
var Ball = function () {
  this.x = width / 2;
  this.y = height / 2;
  this.xSpeed = 5;
  this.ySpeed = 0;
};

// Update the ball's position based on its speed
Ball.prototype.move = function () {
  this.x += this.xSpeed;
  this.y += this.ySpeed;

  if (this.x < 0) {
    this.x = width;
  } else if (this.x > width) {
    this.x = 0;
  } else if (this.y < 0) {
    this.y = height;
  } else if (this.y > height) {
    this.y = 0;
  }
};

// Draw the ball at its current position
Ball.prototype.draw = function () {
  circle(this.x, this.y, 10, true);
};

// Set the ball's direction based on a string

Ball.prototype.setDirection = function() {
  var upPressed = keysDown[directions.up];
  var downPressed = keysDown[directions.down];
  var rightPressed = keysDown[directions.right];
  var leftPressed = keysDown[directions.left];

  if (upPressed) {
    this.ySpeed = -5;
  } else if (downPressed) {
    this.ySpeed = 5;
  }

  if (leftPressed) {
    this.xSpeed = -5;
  } else if (rightPressed) {
    this.xSpeed = 5;
  }
};

// Create the ball object
var ball = new Ball();

// An object to convert keycodes into action names
var directions = {
  left: 37,
  up: 38,
  right: 39,
  down: 40
};

// The keydown handler that will be called for every keypress

var keysDown = {};
$('body').keydown(function(event) {
  keysDown[event.keyCode] = true;
}).keyup(function(event) {
  keysDown[event.keyCode] = false;
});

// The animation function, called every 30 ms
setInterval(function () {
  ctx.clearRect(0, 0, width, height);

  ball.draw();
  ball.move();

  ctx.strokeRect(0, 0, width, height);
}, 30);
       </script>
   </body>
   </html>

If you have tested the code above, you would see that you can move around a little ball with your arrow keys. I was wondering how you could detect multiple arrow keys being pressed down at the same time. So, if I press the down button and the right button, it would move diagonally to the bottom-right corner. How would I code this? An example would be great! Thanks all!

Cool123
  • 37
  • 11

1 Answers1

0

The basic idea for this is you have to keep track of the keys that were pressed, probably in an object, then remove them as they are released.

var keysDown = {};
$('body').keydown(function(event) {
  keysDown[event.keyCode] = true;
}).keyup(function(event) {
  keysDown[event.keyCode] = false;
});

You can then reference those keys when changing direction.

// This is easier if you switch the way you save direction
var directions = {
  up: 38,
  down: 40,
  ...
};
Ball.prototype.setDirection = function() {
  var upPressed = keysDown[directions.up];
  var downPressed = keysDown[directions.down];
  ...

  if (upPressed) {
    this.ySpeed = -5;
  } else if (downPressed) {
    this.ySpeed = 5;
  }

  if (leftPressed) {
  ...
};
Mike Cluck
  • 31,869
  • 13
  • 80
  • 91
  • I'm sorry, but i filled in your suggestions and it didn't work for me – Cool123 Feb 17 '16 at 17:24
  • @Cool123 What about it didn't work? [Here's a working example](https://jsfiddle.net/sj8gvzp4/1/). I'm just printing the location but what matters is that the x and y are updating correctly. – Mike Cluck Feb 17 '16 at 17:33
  • Here, I will re-edit the question I made and let you see. – Cool123 Feb 17 '16 at 17:37
  • @Cool123 You didn't switch your `directions` variable like I did. It won't work because there is no `directions.up` etc. Plus, you're setting the `x` in `setDirection` now instead of `xSpeed`. – Mike Cluck Feb 17 '16 at 17:49
  • @Cool123 That's because you aren't calling `ball.setDirection()`. Call it just before `ball.move()`. – Mike Cluck Feb 17 '16 at 19:08
  • @Cool123 [I modified your code](https://jsfiddle.net/31qs0723/) to include the call to `ball.setDirection()` as well as set the speeds to 0 when no buttons are pressed. – Mike Cluck Feb 17 '16 at 19:12
  • 1
    Thanks for your help Mike! – Cool123 Feb 17 '16 at 19:14
  • Wait... but if you move diagonally, the speed is double because the speeds are getting doubled up – Cool123 Feb 17 '16 at 19:22
  • @Cool123 Sort of. If you want to move half vertical speed, half horizontal speed when moving diagonally, just add another `if` clause to handle that. – Mike Cluck Feb 17 '16 at 19:22
  • Ok, ill see if i can do that – Cool123 Feb 17 '16 at 19:23