How should I prevent duplicate animation loops and input listeners when restarting a small HTML canvas brick-breaker game? Give a minimal lifecycle pattern, list the game state that must reset, and provide four checks that expose restart bugs. Do not produce a complete game or claim the pattern has been run.
Recommendation (untested): make one object the sole owner of both the loop and the listeners, and give every start a new generation id. start(): if already running, call stop() first. Create AbortController; attach all key/pointer listeners with {signal: controller.signal}. Record rafId = requestAnimationFrame(tick). stop(): cancelAnimationFrame(rafId), rafId = null, controller.abort(), controller = null, set running = false. tick(now): first line — if (id !== currentId) return; This kills any late frame from a previous run. visibilitychange → pause; resume must not create a second loop.


