How can I get my JavaScript game to stop freezing every couple of seconds?

I am writing a Pac-Man game, and so far I’ve got the movement and animation down but for some reason, Pac-Man just keeps freezing every 2 seconds or so. It’s very slight and quick, but noticeable enough. Maybe this has something to do with my browser (Google Chrome) or the way I’m setting up the setTimer functions? I’m also aware of the canvas feature in JavaScript, I just wanted to make this game without it for a challenge.

script.js:

let pacMan;
let keyPressed;
let keys = [];

/**
 * Creates a new Pac-Man <img> element and appends it to the document's body.
 * @param {string} src The path to Pac-Man's png image file.
 * @param {number} positionX Pac-Man's x position in the document's body.
 * @param {number} positionY Pac-Man's y position in the document's body.
 * @param {string} transform Pac-Man's rotation in degrees.
 */
function createPacMan(src, positionX, positionY, transform) {

  pacMan = document.createElement("img");
  pacMan.src = src;
  pacMan.id = "pacMan";
  pacMan.style.transform = transform;
  pacMan.style.left = positionX + "px";
  pacMan.style.top = positionY + "px";
  document.body.appendChild(pacMan);

}

createPacMan("assets/images/pacMan1.png", 0, 0);

let pacManPosition = {

  "x": pacMan.getBoundingClientRect().x,
  "y": pacMan.getBoundingClientRect().y

};

/**
 * Calls itself continuously to test if Pac-Man is moving and moves him.
 */
function movePacMan() {

  switch (keyPressed) {
    case "ArrowUp":
      pacManPosition.y -= 1;
      pacMan.style.top = pacManPosition.y + "px";
      pacMan.style.transform = "rotate(90deg)";
      break;

    case "ArrowDown":
      pacManPosition.y += 1;
      pacMan.style.top = pacManPosition.y + "px";
      pacMan.style.transform = "rotate(-90deg)";
      break;

    case "ArrowRight":
      pacManPosition.x += 1;
      pacMan.style.left = pacManPosition.x + "px";
      pacMan.style.transform = "rotate(180deg)";
      break;

    case "ArrowLeft":
      pacManPosition.x -= 1;
      pacMan.style.left = pacManPosition.x + "px";
      pacMan.style.transform = "rotate(0deg)";
      break;
  }
  setTimeout(movePacMan, 15);
}

movePacMan();

/**
 * Calls itself continuously to test if Pac-Man is moving and animated him.
 */
function animatePacMan() {
  if (keys["ArrowUp"] || keys["ArrowDown"] || keys["ArrowRight"] || keys["ArrowLeft"]) {
    setTimeout(function() {
      document.body.removeChild(pacMan);
      createPacMan("assets/images/pacMan2.png", pacManPosition.x, pacManPosition.y, pacMan.style.transform);
      setTimeout(function() {
        document.body.removeChild(pacMan);
        createPacMan("assets/images/pacMan3.png", pacManPosition.x, pacManPosition.y, pacMan.style.transform);
        setTimeout(function() {
          document.body.removeChild(pacMan);
          createPacMan("assets/images/pacMan1.png", pacManPosition.x, pacManPosition.y, pacMan.style.transform);
        }, 50);
      }, 50);
    }, 50);
  }
  setTimeout(animatePacMan, 165);
}

animatePacMan();

/**
 * Adds an event listener that tests for keydown event and resets the keyPressed
 * array, then gets the key pressed and sets its value in the array to be true.
 */
window.addEventListener("keydown", function(event) {

  if (event.key == "ArrowUp" || event.key == "ArrowDown" || event.key == "ArrowRight" || event.key == "ArrowLeft") {
    keyPressed = "";
    keyPressed = event.key;
    keys[event.key] = true;
  }
});

1 thought on “How can I get my JavaScript game to stop freezing every couple of seconds?”

  1. The recursive call to movePacMan means your call stack grows without bound. This in terms means that the browser will have to page out memory and may explain the performance issue you observed. Use setInterval() instead of the recursive call, or as @mplungjan mentioned requestAnimationFrame().

    Reply

Leave a Comment