javascript - 有没有办法检查每个超时的游戏结束条件,但调用主函数通过单个函数重新启动游戏
问题描述
我正在制作一个游戏,其中我有 5 个玩家,每个玩家都使用一种方法移动,该setTimeout
方法在调用另一种setTimeout
方法后重复。
但是,当游戏结束时,我需要停止所有当前的超时并调用 main 函数重新开始游戏。由于英雄可以通过触摸任何恶棍而被杀死,我必须在他们的超时时检查这种情况。如果在任何超时中满足此条件,则清除所有超时并调用 main 函数重新开始游戏。
问题是许多超时仍在后台进行。有没有办法检查每个超时的游戏结束情况?我认为每个超时最终都会调用主函数。
解决方案
setTimout
返回一个计时器 ID,您可以使用它
clearTimeout
来取消计时器。如果您跟踪这些 id,您可以在游戏结束时取消任何未完成的计时器。
let npcs = [];
let createNPC = (delay, logic) => {
// create a function that runs the NPCs logic
// and then calls setTimeout, storing the timer id
// as a property of the returned function
let runLogic = function () {
logic();
runLogic.timerId = setTimeout(runLogic, delay);
};
// start the NPC running
runLogic.timerId = setTimeout(runLogic, delay);
// return a reference to this function so we
// can store it and use it later
return runLogic;
};
let gameOver = () => {
// loop through all the NPC functions and cancel
// all of their timers
npcs.forEach(npc => {
clearTimeout(npc.timerId);
});
console.log('Game over');
};
// create new NPCs and store them in the npcs array
npcs.push(createNPC(1000, () => console.log('NPC 1 did something')));
npcs.push(createNPC(1500, () => console.log('NPC 2 did something')));
npcs.push(createNPC(2000, () => console.log('NPC 3 did something')));
npcs.push(createNPC(2200, () => console.log('NPC 4 did something')));
// for the purposes of this demo, just end the game after 10 seconds
setTimeout(gameOver, 10 * 1000);
比跟踪一堆计时器更好的方法是使用一个运行整个游戏循环的计时器。因为我们只有一个运行更频繁的计时器,所以我使用setInterval
而不是setTimeout
.
let gameLoopTimer;
let npcs = [];
let createNPC = (delay, logic) => {
let npc = {
logic: logic,
delay: delay,
lastActionAt: Date.now()
};
return npc;
};
let gameLoop = () => {
let now = Date.now();
npcs.forEach(npc => {
// if delay ms have passed since our last action, act again
if (now - npc.lastActionAt >= npc.delay) {
// run the NPC logic
npc.logic();
// update the last action
npc.lastActionAt = now;
}
});
};
let gameOver = () => {
clearInterval(gameLoopTimer);
console.log('Game over');
};
let startGameLoop = () => {
let now = Date.now();
// reset all of the NPC last actions
npcs.forEach(npc => npc.lastActionAt = now);
// start running the game loop
gameLoopTimer = setInterval(gameLoop, 100);
};
// create new NPCs and store them in the npcs array
npcs.push(createNPC(1000, () => console.log('NPC 1 did something')));
npcs.push(createNPC(1500, () => console.log('NPC 2 did something')));
npcs.push(createNPC(2000, () => console.log('NPC 3 did something')));
npcs.push(createNPC(2200, () => console.log('NPC 4 did something')));
startGameLoop();
// for the purposes of this demo, just end the game after 10 seconds
setTimeout(gameOver, 10 * 1000);
推荐阅读
- asp.net-core - asp.net core:如何在通过 AJAX 提交表单时应用 ModelState 错误
- c# - 从 xml 文件中删除标签
- reactjs - 无法在 Docker 容器中使用 TypeScript 启动 React
- javascript - 控制台登录JS没有登录控制台
- lisp - 在 Lisp 中实现无限连续整数列表以进行惰性求值
- c++ - 从 lambda 捕获组无休止地调用复制构造函数
- angular - Angular - 如何销毁动态组件?
- c++ - 禁止编译器警告
- javascript - 服务器运行时的Node.js javascript命令行?
- python - 如果数据类型是“时间戳”,我们可以过滤掉 z-score <-3 或 >3 的记录吗?