首页 > 解决方案 > 如何让我的 JavaScript 游戏每隔几秒停止一次冻结?

问题描述

我正在写一个吃豆人游戏,到目前为止,我已经把动作和动画降低了,但出于某种原因,吃豆人每 2 秒左右就会一直冻结。它非常轻微和快速,但足够明显。也许这与我的浏览器(谷歌浏览器)或我设置setTimer功能的方式有关?我也知道canvasJavaScript 中的功能,我只是想在没有它的情况下制作这个游戏来挑战。

脚本.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;
  }
});

标签: javascript

解决方案


对 movePacMan 的递归调用意味着您的调用堆栈不受限制地增长。这意味着浏览器将不得不调出内存并可能解释您观察到的性能问题。使用 setInterval() 而不是递归调用,或者像@mplungjan 提到的 requestAnimationFrame()。


推荐阅读