javascript - 如何让我的 JavaScript 游戏每隔几秒停止一次冻结?
问题描述
我正在写一个吃豆人游戏,到目前为止,我已经把动作和动画降低了,但出于某种原因,吃豆人每 2 秒左右就会一直冻结。它非常轻微和快速,但足够明显。也许这与我的浏览器(谷歌浏览器)或我设置setTimer
功能的方式有关?我也知道canvas
JavaScript 中的功能,我只是想在没有它的情况下制作这个游戏来挑战。
脚本.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;
}
});
解决方案
对 movePacMan 的递归调用意味着您的调用堆栈不受限制地增长。这意味着浏览器将不得不调出内存并可能解释您观察到的性能问题。使用 setInterval() 而不是递归调用,或者像@mplungjan 提到的 requestAnimationFrame()。
推荐阅读
- oracle - 在 oracle DB 中创建用于查找和删除特定表的外键约束的过程
- picasso - 如何使用 picasso 库从 url 设置 drawableleft 图像?
- ios - Swift 类作为稍后实例化的参数
- css - 在移动设备上的容器中居中标题文本
- wordpress - 使用 PWA 在 Wordpress 标题中显示的 HTML 实体转义代码
- android - 如何为每个拉取请求托管一个 Android APK 文件,以便 QA 可以在合并之前对其进行测试?
- webpack - Webpack 4 - 将字体文件复制到特定位置
- asp.net - 当用户返回按钮或刷新按钮导致页面事件时,我的 asp.net Web 应用程序如何?
- c# - API Gateway Ocelot 不重定向
- sql - SQL Server - 选择日期在目标日期 5 天内的所有记录