manage-game-state

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Game state and loop

游戏状态与循环

Model the game as a small explicit state machine with one owner of the clock. Every transition names its states; behaviour, input, and the interface read the current state rather than a scatter of booleans.
将游戏建模为一个由单一时钟所有者管理的小型显式状态机。每个状态转换都明确指定状态;行为、输入和界面读取当前状态,而非分散的布尔值。

States and transitions

状态与转换

  • Enumerate the states — for example ready, playing, paused, over — and make transitions explicit and total. Do not infer state from side effects.
  • Gate the simulation on the active state: advance gameplay, timers, and physics only while playing.
  • 枚举所有状态——例如就绪(ready)、游戏中(playing)、暂停(paused)、结束(over)——并确保状态转换明确且完整。不要从副作用中推断状态。
  • 根据活跃状态控制模拟进程:仅在游戏中(playing)状态下推进游戏玩法、计时器和物理模拟。

Capture input and pause

输入捕获与暂停

  • Request pointer lock from a user gesture such as a click, never on load. Treat loss of pointer lock and tab blur as a pause: freeze the simulation and the clock, and resume on the next gesture.
  • Make
    pointerlockchange
    idempotent: when
    document.pointerLockElement
    is the canvas, transition ready or paused to playing and leave playing unchanged; only transition playing to paused when the element is no longer the canvas. Never implement it as a toggle. Browsers and automation can both report an already-acquired lock, and a duplicate enter event must not pause the game.
  • Clamp the per-frame delta before integrating anything, as
    build-app
    requires, so a backgrounded tab or a slow frame cannot inject one large step into movement, cooldowns, or the clock.
  • 仅在用户触发手势(如点击)时请求pointer lock,绝不要在页面加载时自动请求。将失去pointer lock和标签页失焦视为暂停操作:冻结模拟和时钟,并在下次用户手势时恢复。
  • 确保
    pointerlockchange
    事件处理具有幂等性:当
    document.pointerLockElement
    为画布时,将就绪(ready)或暂停(paused)状态转换为游戏中(playing)状态,若当前已是游戏中状态则保持不变;仅当画布不再是
    pointerLockElement
    时,才将游戏中状态转换为暂停状态。绝不要将其实现为切换逻辑。浏览器和自动化工具都可能报告已获取锁定的情况,重复的进入事件绝不能导致游戏暂停。
  • 在进行任何集成操作前,限制每帧的delta值(如
    build-app
    所要求的),这样后台标签页或卡顿帧就不会给移动、冷却时间或时钟注入过大的步长。

Reset

重置功能

  • A reset restores every owned system to its ready values — entities, camera, clock, timers, cooldowns, effects, and overlays — not only the player. Route reset through the same setup the initial state uses, so ready and reset cannot drift apart.
  • Transition to
    ready
    explicitly before releasing pointer lock. Never derive the reset state from
    document.pointerLockElement
    ; pointer lock is an input side effect, not the state machine.
  • Define timer semantics once and keep them literal in state and snapshots. A field named
    reload
    is remaining cooldown time:
    0
    means ready, firing assigns a positive duration, and the active loop counts it down to exactly
    0
    . Do not expose a normalized readiness value under that name.
  • 重置操作需将所有受控系统恢复至就绪状态的值——包括实体、相机、时钟、计时器、冷却时间、特效和覆盖层——而不仅仅是玩家状态。通过初始状态使用的同一设置流程来执行重置,确保就绪状态和重置状态不会出现偏差。
  • 在释放pointer lock前,明确转换至
    ready
    状态。绝不要从
    document.pointerLockElement
    推导重置状态;pointer lock是输入的副作用,而非状态机的一部分。
  • 统一定义计时器语义,并在状态和快照中保持字面含义。例如名为
    reload
    的字段代表剩余冷却时间:
    0
    表示就绪,触发时赋予一个正时长,活跃循环会将其递减至恰好
    0
    。不要在该字段下暴露归一化的就绪值。

Prove the loop

验证游戏循环

Drive the full cycle with real input: enter play, lose pointer lock and confirm the clock and simulation freeze, resume, reset and confirm every field returns to its ready value, then reach the end state and restart. Read these from the app's own state snapshot, never from console mutation — manufactured state is not evidence.
Choose the authoring surface with the
build-app
skill and own the loop and lifecycle in the surface that creates the application.
通过真实输入驱动完整循环:进入游戏状态,失去pointer lock并确认时钟和模拟已冻结,恢复游戏,重置并确认所有字段返回至就绪值,然后进入结束状态并重新开始。从应用自身的状态快照中读取这些数据,绝不要通过控制台修改来获取——人工制造的状态不能作为有效证据。
使用
build-app
技能选择创作界面,并在创建应用的界面中掌控游戏循环和生命周期。