You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

addEventListener触发时机异常:游戏首次失败后任意点击即重启

问题描述

出于某些原因,addEventListener在应该触发和不应该触发的场景下都会触发。我开发了一款游戏,玩家未失败时正常进行游戏,仅在失败时可点击屏幕重试。浏览器打开或刷新页面时游戏运行一切正常,但首次失败后,任意点击都会导致游戏从头重启,请问我的代码存在什么问题?

问题代码

function main() {
  setTimeout(function everyFrame() {
    clearCanvas();
    // 游戏未结束时运行逻辑
    if (!isGameOver()) {
      game_over = false;

      // 游戏画面渲染逻辑
    }

    // 游戏结束时运行逻辑
    else if (isGameOver()) {
      game_over = true;

      // 失败画面渲染逻辑

      // 用户点击失败画面时重置游戏
      if (game_over) {
        game_over = false;
        myCanvas.addEventListener("click", restartGame);
      }
    }
    main();
    changingDir = false;
  }, 100);
}
问题原因
  • 核心问题是重复绑定点击事件监听器:你的帧逻辑每100ms就会执行一次,只要游戏判定为结束状态,就会给canvas新增一个restartGame点击事件绑定,没有做去重处理。首次失败后,每100ms就多一个重启函数绑定到点击事件上,所有绑定的函数会在点击时同时触发。
  • 额外的逻辑错误:你在游戏结束分支里刚把game_over设为true,马上又在判断分支里把它重置为false,相当于每帧都会重置状态,但之前绑定的事件监听器不会自动清除,哪怕游戏重新开始,历史绑定的事件依然生效,所以任意点击都会触发重启。
修复方案

推荐使用「全局单次绑定+状态判断」的方案,逻辑最稳定:

  1. 把点击事件绑定移到游戏初始化逻辑里,全局只绑定一次
  2. 在restartGame函数开头先判断当前是否为游戏结束状态,只有处于结束状态才执行重启逻辑,否则直接返回

修复后代码示例

// 初始化阶段只绑定一次点击事件
myCanvas.addEventListener("click", restartGame);

function restartGame() {
  // 只有游戏结束时点击才生效
  if (!isGameOver()) return
  // 原重启游戏逻辑
  // ...
}

function main() {
  setTimeout(function everyFrame() {
    clearCanvas();
    // 游戏未结束时运行逻辑
    if (!isGameOver()) {
      game_over = false;
      // 游戏画面渲染逻辑
    }
    // 游戏结束时运行逻辑
    else {
      game_over = true;
      // 失败画面渲染逻辑
      // 移除原来的事件绑定逻辑
    }
    main();
    changingDir = false;
  }, 100);
}

如果你确实需要仅在游戏结束时才绑定事件,那一定要在绑定前移除之前的监听器,或者加绑定标记避免重复绑定:

// 加绑定标记避免重复绑定
let isRestartListenerAdded = false
function main() {
  setTimeout(function everyFrame() {
    clearCanvas();
    if (!isGameOver()) {
      game_over = false;
      // 游戏重置时重置绑定标记
      isRestartListenerAdded = false
      // 游戏画面渲染逻辑
    }
    else {
      game_over = true;
      // 失败画面渲染逻辑
      if (!isRestartListenerAdded) {
        myCanvas.addEventListener("click", restartGame);
        isRestartListenerAdded = true
      }
    }
    main();
    changingDir = false;
  }, 100);
}

内容的提问来源于stack exchange,提问作者Angel R.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 10:36:05