编辑:我已将此报告为Chromium bug:https://bugs.chromium.org/p/chromium/issues/detail?id=668257
我正在使用JS创建一个带有可以射击的敌人的小型画布游戏。为了测试,我创建了一个标志,作为全局声明 let fancy = true;
,以确定是否使用“花哨”的目标算法。我使得按下P会切换此标志。我的主要函数frame
每秒调用另一个名为autoShoot
的函数五次。autoShoot
使用fancy
标志。
今天,一些奇怪的事情发生了;我不记得是什么改变引起了它。有时,当我按下P键时,autoShoot
的行为就像没有切换fancy
一样。我进行了一些调试,并发现新的切换值在frame
内反映,但在autoShoot
中,该值并未更新。它是间歇性的,并且有时autoShoot
中的值会自动修复(而我什么也没做)。
我将代码简化为以下内容,仍然对我显示出问题。试着按下P键多次。对我来说,在仅按下一两次P键后,这两个值就会“不同步”并显示不同:
(我在Windows 10上运行Chrome“版本54.0.2840.99 m”)
const canvas = document.getElementById("c");
const width = 0;
const height = 0;
const ctx = canvas.getContext("2d");
const ratio =1;// (window.devicePixelyRatio||1)/(ctxFOOOOOOOOFOOOOOOOOOFOOOOO||1);
canvas.width = width*ratio;
canvas.height = height*ratio;
canvas.style.width = width+"px";
canvas.style.height = height+"px";
ctx.scale(ratio, ratio);
function testSet(id, val) {
console.log(id+": "+val);
document.getElementById(id).innerText = val;
}
let fancy = true;
document.body.addEventListener("keydown", function(e) {
if (e.keyCode == 80) {
fancy = !fancy;
console.log("Set fancy to: "+fancy);
}
});
let bullets = Array(2000);
let lastTime = 0, shotTimer = 0;
function frame(time) {
const dt = (time - lastTime)/1000;
lastTime = time;
if ((shotTimer -= dt) <= 0) {
testSet("frame", fancy);
autoShoot();
shotTimer = 0.2;
}
for (let b of bullets) {}
requestAnimationFrame(frame);
}
function autoShoot() {
testSet("autoShoot", fancy);
}
requestAnimationFrame(frame);
<code>
fancy (frame) = <span id="frame"></span><br>
fancy (autoShoot) = <span id="autoShoot"></span>
</code>
<canvas id="c"></canvas>
玩弄一下,以下是一些观察结果:
- 删除以下任何内容都会使问题消失:
- 代码顶部处理画布的任何行,甚至是
const ratio
后的注释。 - 空的
for...of
循环:for (let b of bullets) {}
- 将
let fancy =
改为var fancy =
或者只用fancy =
- 将整个事物放到全局范围之外(使用 IIFE、onload 处理程序或块作用域)
- 代码顶部处理画布的任何行,甚至是
- 增加
bullets
数组的大小会增加出现问题的频率。我想这是因为它使frame
执行时间变长;最初,bullets.length
只有 20,但每次循环迭代都会执行一些更新子弹等操作。
这在您的计算机上是否发生?有没有什么逻辑解释?我试过重新启动浏览器,但没有改变。
autoShoot
需要一些时间来跟随更新。很奇怪。 - Bergi