Edit: Я сообщил об этом как Chromium ошибка: https://bugs.chromium.org/p/chromium/issues/detail?id=668257JS глобальная переменная «let» не обновляется в функции?
Я создаю небольшую игру холст в JS с врагами, которые могут стрелять. Для тестирования я создал флаг, объявленный глобально как let fancy = true;
, чтобы определить, следует ли использовать «фантастический» алгоритм таргетинга. Я сделал это так, чтобы нажатие P переключило этот флаг. Моя основная функция, frame
, вызывает другую функцию, autoShoot
, пять раз в секунду. autoShoot
использует флаг fancy
.
Сегодня началось что-то странное; Я не помню, какие изменения внесли его. Иногда, когда я нажимаю P, autoShoot
действует, как fancy
, не был переключен. Я сделал некоторую отладку и обнаружил, что новое, измененное значение равно, отраженное внутри frame
, но в autoShoot
, значение не обновляется. Это случается с перерывами, и иногда значение в autoShoot
закрепится (без меня ничего не сделало).
Я уменьшил код до следующего, что все еще вызывает проблему для меня. Попробуйте нажать P несколько раз. Для меня эти два значения получить «из синхронизации» и дисплей по-разному после нажатия P только один или два раза:
(Я бегу Chrome «Версия 54.0.2840.99 м» на Windows, 10)
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 (let b of bullets) {}
- изменения
let fancy =
вvar fancy =
или простоfancy =
- взвалив всю вещь из глобальной области (с использованием IIFE, ОНЛ oad handler или scope)
- любой строки в коде на вершине дела с полотном, даже только комментарий после
- Увеличение размера массива
bullets
увеличивает частоту возникновения проблемы. Я думаю, что это связано с тем, чтоframe
занимает больше времени для выполнения; первоначально,bullets.length
было всего 20, но каждая итерация цикла делала некоторые вещи для обновления пули и т. д.
Это происходит на ваших компьютерах? Есть ли для этого логическое объяснение? Я попытался перезагрузить свой браузер, никаких изменений.
nope, никогда не выходит из синхронизации в firefox –
Вопрос немного сложный ... это помогает, если вы предоставляете более простой полный пример, который воспроизводит проблему. –
Я фактически подрезал это до минимального примера, который все еще вызывает поведение. Удаление чего-нибудь еще заставляет его уйти: P – qxz