如何修复Pacman游戏switch按键逻辑中setInterval重复触发bug
吃豆人游戏定时器问题修复方案
问题根源
- 每次触发方向键时没有清除之前的定时器,导致多个定时器同时运行:重复按同一方向时多个定时器同时执行移动逻辑,速度成倍加快;按不同方向时多个方向的移动逻辑交替执行,导致角色来回移动。
修复方法
在每次创建新定时器前,先清除上一个正在运行的定时器,确保全局永远只有一个移动定时器生效。
修复后的完整代码
let myInt = null; // 初始值改为null更合理 function move(e) { // 核心修复:每次触发方向键先清除之前的定时器 if (myInt) clearInterval(myInt); squares[pacManPosition].classList.remove('pac-man'); switch (e.key) { case 'ArrowUp': // 可选优化:按下按键先移动一次,不用等定时器首次触发的延迟 if (!squares[pacManPosition - width].classList.contains('wall')) { pacManPosition -= width; } myInt = setInterval( function () { if (!squares[pacManPosition - width].classList.contains('wall')) { squares[pacManPosition].classList.remove('pac-man'); pacManPosition -= width; squares[pacManPosition].classList.add('pac-man'); // 吃豆逻辑移到定时器里,每次移动后触发 pacdotsEaten(); powerPelletsEaten(); } }, 400) break; case 'ArrowRight': if (!squares[pacManPosition + 1].classList.contains('wall')) { pacManPosition++; } myInt = setInterval( function () { if (!squares[pacManPosition + 1].classList.contains('wall')) { squares[pacManPosition].classList.remove('pac-man'); pacManPosition++; squares[pacManPosition].classList.add('pac-man'); pacdotsEaten(); powerPelletsEaten(); } }, 400) break; case 'ArrowDown': if (!squares[pacManPosition + width].classList.contains('wall')) { pacManPosition += width; } myInt = setInterval( function () { if (!squares[pacManPosition + width].classList.contains('wall')) { squares[pacManPosition].classList.remove('pac-man'); pacManPosition += width; squares[pacManPosition].classList.add('pac-man'); pacdotsEaten(); powerPelletsEaten(); } }, 400) break; case 'ArrowLeft': if (!squares[pacManPosition - 1].classList.contains('wall')) { pacManPosition--; } myInt = setInterval( function () { if (!squares[pacManPosition - 1].classList.contains('wall')) { squares[pacManPosition].classList.remove('pac-man'); pacManPosition--; squares[pacManPosition].classList.add('pac-man'); pacdotsEaten(); powerPelletsEaten(); } }, 400) break; } squares[pacManPosition].classList.add('pac-man'); pacdotsEaten(); powerPelletsEaten(); } // 可选优化:把事件从keyup改成keydown,按下按键立刻响应,体验更流畅 document.addEventListener('keydown', move);
额外优化建议
- 可以把四个方向的重复逻辑抽成公共函数,减少代码冗余
- 如果需要支持松开按键停止移动,可以监听keyup事件,在松开时执行
clearInterval(myInt)
内容的提问来源于stack exchange,提问作者saud
相关产品推荐
相关产品推荐

