首页 > 解决方案 > 有没有办法检查每个超时的游戏结束条件,但调用主函数通过单个函数重新启动游戏

问题描述

我正在制作一个游戏,其中我有 5 个玩家,每个玩家都使用一种方法移动,该setTimeout方法在调用另一种setTimeout方法后重复。

但是,当游戏结束时,我需要停止所有当前的超时并调用 main 函数重新开始游戏。由于英雄可以通过触摸任何恶棍而被杀死,我必须在他们的超时时检查这种情况。如果在任何超时中满足此条件,则清除所有超时并调用 main 函数重新开始游戏。

问题是许多超时仍在后台进行。有没有办法检查每个超时的游戏结束情况?我认为每个超时最终都会调用主函数。

标签: javascripthtmlweb

解决方案


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);


推荐阅读