mcpField
G
game-architecture

game-architecture

github.com/hungify开发016 次安装1 周前更新
代码仓库

关于 game-architecture

这是一份适用于 Three.js 或 Phaser 浏览器游戏的架构参考技能,指导开发者组织核心玩法、状态与事件管理,并检查重启清理和发布前验证。

主要功能

  1. 01优先实现核心玩法循环
  2. 02基于 EventBus 的模块通信
  3. 03集中管理游戏状态与常量
  4. 04使用编排器管理游戏流程
  5. 05重启安全的清理实践
  6. 06发布前验证清单

适用场景

  1. 01规划浏览器游戏架构
  2. 02拆分游戏系统与玩法模块
  3. 03避免重启后残留监听器和资源
  4. 04检查输入、响应式布局与构建

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/hungify/playables-skills --skill game-architecture

安装后在 Claude Code 中输入/game-architecture确认已加载。

附带文件system-patterns.md

详细介绍

游戏架构模式

用于构建结构良好的浏览器游戏的参考知识。这些模式适用于 Three.js(3D)和 Phaser(2D)游戏。

参考文件

详细参考内容请参阅此目录中的配套文件:

  • system-patterns.md — 对象池、delta 时间归一化、资源释放、波次/生成系统、增益/强化道具系统、触觉反馈、资源管理

核心原则

  1. 优先实现核心循环:先实现最基本的游戏玩法循环,再进行任何润色。顺序为:输入 -> 移动 -> 失败条件 -> 计分 -> 重新开始。只有核心循环正常运行后,才能添加视觉效果、音频或爽快感效果。初始范围要小:1 个场景/关卡、1 个机制、1 个失败条件。

  2. 事件驱动通信:模块之间不得通过相互导入来通信。所有跨模块消息都通过带有预定义事件常量的单例 EventBus 传递。

  3. 集中管理状态:单个 GameState 单例保存所有游戏状态。系统直接读取状态,并通过事件修改状态。不得在各模块中分散存储状态。

  4. 集中管理配置:所有魔法数字、平衡值、资源路径、生成点和时间值都放入 Constants.js。游戏逻辑文件中不得包含任何硬编码值。

  5. 编排器模式:一个 Game.js 类负责初始化所有系统、管理游戏流程(启动 -> 游戏中 -> 死亡/胜利 -> 重新开始)并运行主循环。系统不得自行初始化。默认不设标题画面——直接启动游戏。只有用户明确要求时,才添加标题/菜单场景。

  6. 安全重启且保持确定性:游戏玩法必须能够在完整重启后正常运行。GameState.reset() 会恢复完整的初始状态。清理/关闭时必须移除所有事件监听器。重启后不得残留过期引用、计时器、补间动画或孤立的物理实体。连续重启 3 次进行测试——第三次运行必须与第一次表现一致。

  7. 明确区分职责:代码按功能层组织:

    • core/ - 基础组件(Game、EventBus、GameState、Constants)
    • systems/ - 引擎级系统(输入、物理、音频、粒子)
    • gameplay/ - 游戏机制(玩家、敌人、武器、计分)
    • level/ - 世界构建(关卡构建、资源加载)
    • ui/ - 界面(菜单、HUD、叠加层)

事件系统设计

事件命名约定

使用按功能领域分组的 domain:action 格式:

export const Events = {
    // Player
    PLAYER_DAMAGED: 'player:damaged',
    PLAYER_HEALED: 'player:healed',
    PLAYER_DIED: 'player:died',

    // Enemy
    ENEMY_SPAWNED: 'enemy:spawned',
    ENEMY_KILLED: 'enemy:killed',

    // Game flow
    GAME_STARTED: 'game:started',
    GAME_PAUSED: 'game:paused',
    GAME_OVER: 'game:over',

    // System
    ASSETS_LOADED: 'assets:loaded',
    LOADING_PROGRESS: 'loading:progress'
};
事件数据契约

始终传递结构化数据对象,不要传递原始值:

// Good
eventBus.emit(Events.PLAYER_DAMAGED, { amount: 10, source: 'enemy', damageType: 'melee' });

// Bad
eventBus.emit(Events.PLAYER_DAMAGED, 10);

状态管理

GameState 结构

将状态划分为清晰的领域:

class GameState {
    constructor() {
        this.player = { health, maxHealth, speed, inventory, buffs };
        this.combat = { killCount, waveNumber, score };
        this.game = { started, paused, isPlaying };
    }
}

游戏流程

适用于 2D 和 3D 游戏的标准流程:

Boot/Load -> Gameplay <-> Pause Menu (if requested)
                      -> Game Over -> Gameplay (restart)

**默认不设标题画面。**游戏直接启动。Play.fun 小组件会在游戏顶部的死区内处理分数显示、排行榜和钱包连接,因此无需在游戏内设置分数 HUD。只有用户明确要求时,才添加标题/菜单场景。

常见架构陷阱

  • 未连接的物理体 — 创建静态物理体(例如地面、墙壁)后,如果没有通过 physics.add.collider() 或 physics.add.overlap() 将其与其他物体连接,就不会对游戏玩法产生任何影响。每个边界或障碍物都需要明确连接到它应当与之交互的实体。创建任何静态物体后,应立即添加碰撞器调用。
  • 交互元素被重叠的显示对象挡住 — 构建 UI(按钮、菜单)时,场景列表中最上层的显示对象会接收指针事件。切勿将交互元素藏在装饰层后面。可以让视觉元素本身支持交互,或者确保命中区域上方没有渲染任何内容。
  • 先打磨,后做玩法 — 在核心循环正常运作之前添加粒子效果、屏幕抖动和转场,是常见的时间陷阱。先让输入 -> 操作 -> 失败条件 -> 计分 -> 重新开始正常运作。其他一切都属于润色。
  • 重新开始时未清理 — 忘记移除事件监听器、销毁计时器以及在 shutdown() 中释放资源,会导致重新开始后出现异常行为、事件重复触发和内存泄漏。

发布前验证清单

在认定游戏已完成之前,请确认所有项目均已通过验证:

  • 核心循环 — 玩家可以开始游戏、进行游戏、输赢,并查看结果
  • 重新开始 — 连续运行 3 次,行为一致且无异常
  • 移动设备输入 — 触摸/轻触/滑动/陀螺仪均可正常工作;点击目标最小尺寸为 44px
  • 桌面设备输入 — 键盘和鼠标均可正常工作
  • 响应式布局 — 窗口大小改变时,画布能正确调整尺寸
  • 常量 — 游戏逻辑中没有硬编码的魔法数字
  • EventBus — 模块间通信没有直接跨模块导入
  • 清理 — 关闭时移除所有监听器,并释放资源
  • 静音切换 — 请参阅 mute-button 规则
  • 基于 delta 的移动 — 所有移动都使用 delta 时间,而非帧数
  • 构建 — npm run build 成功,且没有错误
  • 无错误 — 运行时没有未捕获的异常或控制台错误

评论

支持 Markdown