0

window.onload = function() {
  canv = document.getElementById("gc");
  canv.width = 500;
  canv.height = 300;
  ctx = canv.getContext("2d");
  document.addEventListener("keydown", keyDown);
  setInterval(game, 10);
}

function Paddle(x, y) {
  this.x = x;
  this.y = y;
  this.l = 50;
  this.score = 0;
}

function Ball(x, y, xv, yv) {
  this.x = x;
  this.y = y;
  this.xv = xv;
  this.yv = yv;
  this.s = 5;
  this.update = function() {
    this.x += this.xv;
    this.y += this.yv;
  }
}

function drawLine(x1, y1, x2, y2) {
  ctx.beginPath();
  ctx.moveTo(x1, y1)
  ctx.lineTo(x2, y2)
  ctx.stroke();
  ctx.closePath();
}

function random(min, max) {
  var i = 0;
  while (!i) {
    i = Math.floor(Math.random() * (max - min + 1) + min);
  }
  return i;
}

p1 = new Paddle(10, 125);
p2 = new Paddle(490, 125);
b = new Ball(250, 150, random(-2, 2), random(-2, 2));

function game() {
  b.update();
  if (p1.y < 0)
    p1.y = 0;
  else if (p1.y + p1.l > canv.height)
    p1.y = canv.height - p1.l;
  if (p2.y < 0)
    p2.y = 0;
  else if (p2.y + p2.l > canv.height)
    p2.y = canv.height - p2.l;
  if (b.y < 0 || b.y > canv.height)
    b.yv = -b.yv;
  if (b.x < 0) {
    p2.score++;
    b = new Ball(30, 150, random(0, 2), random(-2, 2));
  } else if (b.x > canv.width) {
    p1.score++;
    b = new Ball(canv.width - 30, 150, random(-2, 0), random(-2, 2));
  }
  if ((b.x == p1.x && b.y > p1.y && b.y + b.s < p1.y + p1.l) ||
    b.x + b.s == p2.x && b.y > p2.y && b.y + b.s < p2.y + p2.l)
    b.xv = -b.xv;
  ctx.fillStyle = "black";
  ctx.fillRect(0, 0, canv.width, canv.height);
  ctx.strokeStyle = "white";
  drawLine(p1.x, p1.y, p1.x, p1.y + p1.l);
  drawLine(p2.x, p2.y, p2.x, p2.y + p2.l);
  ctx.fillStyle = "white";
  ctx.fillRect(b.x, b.y, b.s, b.s);
  ctx.font = "30px sans serif";
  ctx.fillText(p1.score, 200, 50);
  ctx.fillText(p2.score, 300, 50);
}

function keyDown(evt) {
  switch (evt.keyCode) {
    case 83:
      p1.y += 10;
      break;
    case 87:
      p1.y -= 10;
      break;
    case 40:
      p2.y += 10;
      break;
    case 38:
      p2.y -= 10;
      break;
  }
}
<canvas id="gc"></canvas>

In this rudimentary Pong program, I use document.addEventListener("keydown", keyDown); to control the movement of the paddles. But, the function is not being called at a consistent rate (the movement is not fluid). The first press is registered, then a slight pause, and THEN it moves fluidly. (Similar to if you hold a letter key down, it types one letter. If you continue holding it, it continues to type letters, but not before a slight pause? Not sure if I'm being clear here...)

Is there a way to have consistent input/function calls using the "keydown" event listener?

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
dav
  • 626
  • 4
  • 21
  • Sounds like you want to ["debounce"](https://stackoverflow.com/q/24004791/215552) your event handling so that it becomes more consistently timed. – Heretic Monkey Jun 21 '17 at 20:30
  • 1
    not necessarily. input is fluid after the first function call, it's just the gap between the first and the second that is odd. – dav Jun 21 '17 at 20:39
  • 1
    That's down to your operating system's key repeat rate. What OS are you using? – joews Jun 21 '17 at 20:47
  • 3
    Possible duplicate of [remove key press delay in javascript](https://stackoverflow.com/questions/3691461/remove-key-press-delay-in-javascript) – Heretic Monkey Jun 21 '17 at 20:48
  • Ah ok. I'm using Windows. Is the "debounce" function the only workaround? – dav Jun 21 '17 at 20:48
  • 2
    Set a flag on `keydown`, and unset it on `keyup`. Check the state of the flag in each `requestAnimationFrame` callback (or however else you run your game loop). – joews Jun 21 '17 at 20:49
  • Yes it does appear to be a duplicate. I wasn't searching for the right terms. That thread seems to help. Thanks! – dav Jun 21 '17 at 20:49

1 Answers1

1

You can smooth out the effect of your OS keyboard repeat rate by setting the value of a variable on keydown, and clearing it on keyup. For example:

let direction = null;

document.addEventListener("keydown", function (evt) {
  switch (evt.keyCode) {
    case 83:
      direction = "down";
      break;
    case 87:
      direction = "up";
      break;
    case 40:
      direction = "down";
      break;
    case 38:
      direction = "up";
      break;
    default:
      direction = null;
  }
});

document.addEventListener("keyup", function (evt) {
  direction = null;
})

Check the state of this variable on each iteration of your game loop. Most HTML5 games use requestAnimationFrame for that.

joews
  • 29,767
  • 10
  • 79
  • 91