# cc383script2d **Repository Path**: moho721/cc383script2d ## Basic Information - **Project Name**: cc383script2d - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-05 - **Last Updated**: 2026-09-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # cc383script2d > Cocos Creator 3.8.3 2D 游戏工厂型脚本基座 > > **定位**:通过更换资源、微调配置参数,快速产出多个不同风格的 2D 生存/沙盒游戏。 > **设计原则**:通用、可扩展、组件组合、事件驱动、配置驱动。 > > **当前状态**:主干进入**稳定期(冻结)** — 基座 `_BaseClassScript/`(20 文件)与 Phase 1~4.1 已收敛;主干只收关键 bug 修复 + 纯数据配置;玩法扩充走「配置 / 叶子子类 / 宿主验证」,**玩法系统入 `extensions/` 插件层**(见 §开发策略)。联机客户端核心 ✅(Phase 4.1);服务器权威共享敌人由宿主完成(Phase 4.2/4.3);本仓库补充 **P4-4 网络 uid 与本地实体 uid 统一**(服务器→玩家伤害走游戏自身管线)。 --- ## 愿景 这是一个"工厂型项目底子"——不是为某一个具体游戏而写,而是为**一类游戏**(2D 生存/沙盒/动作 RPG)提供可复用的底层架构。 核心思路: - **纯 TypeScript 设计**,在 Cocos Creator 编辑器外完成脚本架构,再导入项目 - **资源无关**,不硬编码任何资源路径,所有资源引用通过 CC 编辑器拖拽绑定 - **配置驱动**,所有游戏参数通过 `@property` 装饰器或配置对象暴露,不改代码即可调参 - **组件组合**,节点通过附加多个 Component 组合功能,而非深继承 - **事件驱动**,模块间通过 EventBus 通信,降低耦合,方便后续替换/扩展 - **联机预留**,架构设计考虑网络同步,后续可接入联机功能 --- ## 架构总览 ``` _BaseClassScript/ ├── Core/ # 核心系统 │ ├── BaseEntity.ts # 实体基类(HUD + 生命周期 + 钩子) │ ├── BaseAnimation.ts # 方向帧动画组件(独立,可挂载到任何节点) │ ├── CameraController.ts # 摄像机跟随(独立组件) │ ├── EventBus.ts # 全局事件总线(解耦通信) │ └── GameManager.ts # 游戏管理器(启动脚本,串联所有系统) │ ├── Life/ # 生命体系统 │ ├── BaseLife.ts # 生命体基类(三围 + 移动 + 战斗) │ ├── PlayerController.ts # 玩家输入控制(WASD + 交互 + 攻击) │ └── EnemyAI.ts # 敌人AI(有限状态机:巡逻/索敌/追击/攻击) │ ├── Item/ # 物品系统 │ ├── BaseItem.ts # 物品基类(耐久度 + 三种状态切换) │ ├── Inventory.ts # 背包系统(格子 + 堆叠 + 热键栏 + 装备栏) │ └── ItemFactory.ts # 物品工厂(从配置模板生成物品实例) │ ├── World/ # 世界系统 │ ├── BaseDestructible.ts # 可破坏物体基类(血量 + HUD + 掉落 + 破坏阶段) │ └── WorldManager.ts # 世界管理(实体生成/销毁/掉落) │ ├── Combat/ # 战斗系统 │ └── CombatManager.ts # 战斗管理(伤害计算/装备加成/命中判定) │ └── Network/ # 联机系统(客户端核心,Phase 4.1 ✅) ├── NetProtocol.ts # 消息协议(信封/类型/编解码)— 纯 TS ├── NetState.ts # 实体序列化(uid)/去抖/快照 diff — 纯 TS ├── NetTransport.ts # 传输适配器(WebSocket + Loopback)— 纯 TS ├── NetSyncCore.ts # 出入站映射/快照应用 — 纯 TS └── NetworkSync.ts # 联机组件(cc 薄接线层) ``` > 基座之外:**玩法系统**以插件形式放同级 `extensions//`(见 §开发策略插件层),不进基座。 --- ## 类继承关系 ``` Component (cc) ├── BaseEntity # 实体基类 │ ├── BaseLife # 生命体(移动、三围、战斗) │ │ ├── ← PlayerController # (附加组件) 玩家输入 │ │ └── ← EnemyAI # (附加组件) 敌人AI │ ├── BaseItem # 物品(耐久度、状态切换) │ └── BaseDestructible # 可破坏物体(血量、被摧毁) │ ├── Building # 建筑(墙壁、工作台等) │ └── Harvestable # 可采集物(树木、矿石等) ├── BaseAnimation # (独立组件) 方向帧动画 ├── CameraController # (独立组件) 摄像机跟随 ├── GameManager # (启动脚本) 游戏管理器,串联所有系统 └── (其他 CC 组件按需附加) ``` --- ## 设计原则 ### 1. 组件组合 → 非深继承 ```typescript // 玩家节点:同时挂载多个组件 // Player Node // ├── BaseLife → 生命、移动、战斗 // ├── BaseAnimation → 方向帧动画 // ├── PlayerController → 键盘输入 // └── Inventory → 背包管理 // 敌人节点 // Enemy Node // ├── BaseLife → 生命、移动、战斗 // ├── BaseAnimation → 方向帧动画 // └── EnemyAI → 自动AI行为 // 游戏管理器(场景中一个空节点) // GameManager Node // └── GameManager → 启动脚本,串联所有系统 ``` ### 2. 钩子方法 → 子类按需重写 基类提供 protected 钩子方法,子类或具体游戏脚本重写以定制行为: ```typescript class BaseEntity { protected onScheduledTick(): void {} // 每秒定时回调 protected onTakeDamage(amount: number, source?: BaseLife): void {} // 受伤回调 protected onDeath(): void {} // 死亡回调 protected updateHUD(): void {} // HUD更新 } class BaseItem { protected onUse(user: BaseLife): void {} // 使用物品 protected onEquip(user: BaseLife): void {} // 装备时 protected onUnequip(user: BaseLife): void {} // 卸下时 protected onPickup(): void {} // 拾取时 protected onDrop(): void {} // 丢弃时 } ``` ### 3. 事件驱动 → 模块间解耦 ```typescript // EventBus 事件列表 EventBus.on('ENTITY_DAMAGED', (data) => { /* UI更新、音效、网络同步 */ }); EventBus.on('ENTITY_DIED', (data) => { /* 掉落物品、播放死亡动画 */ }); EventBus.on('ENTITY_REPAIRED', (data) => { /* 建筑维护、耐久恢复反馈 */ }); EventBus.on('ENTITY_DESPAWNED', (data) => { /* 世界清理、网络同步 */ }); EventBus.on('ITEM_PICKED_UP', (data) => { /* 背包更新、音效 */ }); EventBus.on('ITEM_USED', (data) => { /* 属性恢复、消耗品减少 */ }); EventBus.on('ITEM_DROPPED', (data) => { /* 地图生成物品实体 */ }); EventBus.on('ENEMY_AGGRO', (data) => { /* 敌人进入战斗状态 */ }); EventBus.on('PLAYER_ATTACK', (data) => { /* 攻击判定 */ }); EventBus.on('INVENTORY_CHANGED', (data) => { /* UI刷新、网络同步 */ }); ``` ### 4. 配置驱动 → 不改代码调参数 所有游戏参数通过 CC `@property` 装饰器暴露,在编辑器中拖拽调整: ```typescript @property maxHealth: number = 100; @property moveSpeed: number = 200; @property hungerDecreaseRate: number = 1; ``` --- ## 开发策略:主干稳定 + 玩法低风险扩充 **目标**:主干(master)长期稳定——降低出问题概率与人工 review 难度;游戏玩法继续丰富,但一律走**低风险路径**,不增加主干架构复杂度。 ### 主干边界(冻结区) 主干只收两类改动,其余一律走分支 / 独立仓库: - **关键 bug 修复**(复现 → 根因 → 最小改动 → 宿主复验); - **纯数据配置增补**:`ItemFactory` 物品模板、敌人掉落表(`NORMAL/ELITE_ENEMY_DROPS`)、`Harvestable` 掉落表、开局物品表、`EnemyAI` tier 数值。 **冻结**:基座 `_BaseClassScript/` 内的基类接口 / 继承关系、模块新增、EventBus 事件契约、消息协议(NetProtocol)等架构性改动**不再进主干**(Network 五文件是基座内最后一批新增文件);确有必要时开 feature 分支,稳定 + 评审通过后再合。**玩法系统一律走 `extensions/` 插件层**(见下),不属于基座新增。 ### 玩法扩充路径(风险从低到高) | 层级 | 做法 | 例子 | 进主干? | |------|------|------|---------| | **L0 配置** | 只改数据不改逻辑(模板 / 掉落表 / 开局表 / 数值) | 新增物品、调掉落、调敌人数值 | ✅ 直接进,diff 小易 review | | **L1 叶子子类** | 新增**单个具体类**继承基类、重写钩子,**不改任何基类** | `Harvestable`(采集物)、`Building`(建筑)、新敌人类型 | ✅ 单文件新增 + 宿主验证后进 | | **L2 宿主验证** | 玩法先在 `cc383script2d-host` 可视化试玩 + 无头测试验证 | 新物品图标、采集 / 掉落闭环、幽灵表现 | 必经步骤(验收入口) | | **L3 系统插件** | 在 `extensions//` 新建**自包含插件**,只依赖基座,**不改基座代码** | 合成、建造、buff、地图生成… | ✅ 进本仓库插件层,单插件独立评审 | | **L4 改基座** | 修改基类接口 / 继承关系 / 事件契约 / 协议 | 基类改造、协议扩展、服务器权威化 | ❌ 走 feature 分支,评审通过才合 | > **通俗版**:L0=只改数据不改代码;L1=新加一个东西(继承已有类),不改任何旧东西;L2=先在宿主试玩 + 自动测试;L3=做成独立插件(日常新玩法都走这个,不碰基座);L4=改基座代码(冻结区,最重,要评审)。**日常做玩法基本只用 L1 和 L3。** ### 插件层(extensions/)— 玩法系统放这里,不进基座 **目的**:基座保持精简、稳定、跨游戏可复用;玩法系统作为**自包含插件**放同级 `extensions/`,随本仓库一起分发,游戏项目按需选用——避免"太 base 导致无法大量复用"。 **插件契约**: 1. 每个插件 = `extensions//` 一个自包含目录,只依赖基座(`_BaseClassScript/`),**不依赖其它插件**; 2. 通过**基类钩子 / EventBus** 与基座交互(可自定义事件名,不动核心契约),**禁止修改基座代码**; 3. **可选加载**:游戏项目引入需要的插件,未引入的不受影响; 4. 每个插件自带宿主无头测试 / 自检断言(L2 验收入口); 5. 命名建议:`extensions/crafting`、`extensions/building`、`extensions/buff`…(候选见 §玩法丰富方向)。 > **参考实现**:`_BaseClassScript/World/Harvestable.ts` 是目前唯一的叶子子类范例——演示了「不改基座、只继承 + 重写钩子」的接入方式,也是第一个**待迁入** `extensions/harvesting/` 的候选(迁移需宿主 build 支持第二源码根)。 > > **通用系统插件范例**:`extensions/runtime-assets/`(2026-09-03,通用资产管线)——`AssetProvider` 接口 + 槽位约定 + 元素映射 + 精灵状态机,纯 TS、零依赖、**游戏侧不知上层实现**;任一新宿主(host1/host2/…)实现 `AssetProvider` 接口即可整套复用。见 extensions/README。 > > **玩法插件范例(2026-09-03 落地)**:`extensions/crafting/`(合成:`Recipes` 纯数据 + `CraftingManager` 鸭子类型背包核心 + `CraftingTable` 薄 cc 合成台)、`extensions/saving/`(存档:`SaveFormat`/`SaveManager` 版本化快照核心 + `GameSaveController` 薄 cc 接线)、`extensions/buff/`(状态效果:`Buffs` + `BuffSystem` 纯核心 + `BuffController` 薄 cc),均「纯 TS 核心 + 薄 cc 层 + selfcheck」,宿主 `tests/plugins.mjs` 一键验证。 ### 插件隔离与收敛(2026-09-04)—「新插件出问题绝不影响已稳定部分」 **目标**:主干 + N 个已稳定插件之后,新增第 N+1 个插件若带问题,必须: - **运行期**完全不影响已稳定插件与主干(报错不扩散、UI 不崩、事件不串); - **加载期**失败也不拖垮其它插件(整体照常启动); - **无需动任何已有部分**,只修新插件 + 它自己的自检,最终收敛为「稳定主干 + N+1 插件」。 **在 §插件层 既有契约上的强化**: | 机制 | 说明 | |------|------| | **注册式加载** | 主干只通过**插件注册表 / 清单**发现插件,不静态 `import` 任何插件 → 编译期主干零插件依赖;插件缺失 / 加载失败不影响主干编译与启动 | | **接口即契约(interface-first)** | 主干暴露**冻结**的接口 / 事件 / 服务(钩子、EventBus 事件名、配置 schema);插件只依赖接口。插件之间**禁止 import**;横向功能经「可选服务接口 + 运行时注册」协作,无编译期依赖 | | **错误围栏(error containment)** | EventBus 监听器**逐个隔离**(一个抛出不影响其它监听器);每插件入口统一 `try/catch` + 状态上报;插件运行异常 → 打日志 + 标记「已禁用」,主干与其它插件照常运行 | | **可拔插 / 可禁用** | 每插件可在配置文件里开关;禁用 = 其注册的钩子 / 事件 / 内容全部不生效,世界表现等同「该插件不存在」 | | **自带自检 + 三档回归** | 每插件自带无头自检;宿主 CI 跑三档:① 基线(主干 alone)② 正交(主干 + 每个插件)③ 全量(主干 + 全部插件)→ 新增插件出问题可定位到「它自己」,并证明不影响其它稳定块 | | **契约版本** | 主干接口契约打版本号,插件声明目标契约版本;不匹配在**加载期**明确报错,而非运行期诡异行为 | | **修复即收敛(fix-in-place)** | 新插件带 bug 的标准流程:配置文件**关掉它**(稳定部分无感)→ 只修它自己 + 跑它自检 + 全量回归 → 重新打开 → 收敛为「稳定主干 + N+1 插件」 | > 一句话:**先关掉、只修它、再打开** —— 不允许为了一个新插件去动任何已稳定的代码。 ### Review 门槛(人工 review 清单) 1. **基类文件**(`BaseEntity / BaseLife / BaseItem / BaseAnimation / EventBus / WorldManager / Inventory / GameManager / …`)有 diff 时,必须说明「为何不能被子类或配置替代」; 2. **新增文件**:叶子子类尽量薄、只重写钩子、不改基类;新增架构文件走分支评审; 3. **每次玩法改动**附带宿主无头测试 / 自检断言(回归锁定); 4. 主干 diff 尽量**小而数据化**——L0 配置类是常态,L3 是例外。 --- ## 内容配置化(内容即数据) **原则**:一切「有多种类」的内容都以**人工易读易改的配置文件**定义,作者可自行添加条目、**不改任何代码**。凡「同一种东西的不同变体」——物品 / 武器 / 防具 / 消耗品、掉落表、采集物、敌人 / Boss、任务、成就 / 称号、buff / 词条 / 技能、宠物、城池 / 据点、NPC 对话、商城商品、日常 / 通行证、副本 / 巢穴、坐骑 / 载具 / 巨型形态……都应从代码里走出来、进配置。 **形态与约定**: - **一个分类一个目录**:`content/<分类>/`(JSON 或 TS 数据模块,纯数据、人工可写);分类示例:`item` `enemy` `boss` `quest` `achievement` `title` `buff` `affix` `skill` `pet` `city` `npc_dialog` `shop` `dungeon` `ride`… - **命名即契约**:条目 `id` 直接决定资产槽位路径,与 `extensions/runtime-assets` 的 `AssetSlots` 约定联动(`<元素>/<时机>[/<方向>]`,帧 `0.png 1.png …`): - 物品 `iron_sword` → `assets/item/iron_sword/...` - Boss `dragon` → `assets/boss/dragon/...` - NPC `blacksmith` → `assets/npc/blacksmith/...` - 载具 / 坐骑 / 巨型形态 → `assets/ride//...` - 缺图回退色块 / 图标(复用 runtime-assets 回退规则)。 - **配置校验 fail fast**:每分类带 schema 校验器 + 资产存在性检查,启动 / 自检时报错指明「哪个分类 / 哪个 id / 缺哪张图 / 哪个字段非法」。 - **统一加载器**:主干提供统一内容加载器(读配置 → 校验 → 注入 ItemFactory / 掉落表 / 任务表 / 商城表 …);插件可声明自己的配置分类并复用同一加载器。 - **L0 配置表并入**:现有 ItemFactory 模板、敌人 / 采集物掉落表、开局物品表、EnemyAI tier 数值统一归入本层,成为「配置化的第一批」。 > 目标:**新玩法内容 = 写配置 + 放图,零代码**。 --- ## 模块说明 ### Core / BaseEntity.ts 所有实体对象的基类,提供最基础的生命周期和 HUD 能力。 | 属性 | 类型 | 说明 | |------|------|------| | `entityId` | `string` | 实体唯一标识 | | `nameLabel` | `Label` | 实体名称标签 | | `iconSprite` | `Sprite` | 实体图标 | | 方法 | 说明 | |------|------| | `start()` | 启动定时回调 + 更新HUD | | `onScheduledTick()` | 每秒定时回调,子类重写 | | `updateStatDisplay(text, bar, current, max)` | 更新文本+进度条显示 | | `updateHUD()` | 子类重写,调用 `updateStatDisplay` 更新各自 HUD | | `onTakeDamage(amount, source?)` | 受伤回调,子类可重写 | | `onDeath()` | 死亡回调,子类可重写 | ### Core / BaseAnimation.ts 方向帧动画组件,独立于任何实体,可挂载到需要动画的节点上。 | 属性 | 类型 | 说明 | |------|------|------| | `animationFrames` | `Node[]` | 帧节点数组 | | `animationSpeed` | `number` | 帧切换速度(秒) | | `frameSize` | `number` | 每帧大小 | | `framesPerDirection` | `number` | 每方向帧数(可配置,不再硬编码为2) | | `directionCount` | `number` | 方向数(4 或 8,默认 8;4 = 兼容旧四方向布局,8 = 新增 4 个斜向) | | 方法 | 说明 | |------|------| | `setMoving(moving)` | 设置移动状态,停止时回到第一帧 | | `setDirection(direction: Vec2)` | 根据移动方向设置动画方向 | | `playOnce(frameStart, frameEnd, callback?)` | 播放一次性动画(攻击、死亡) | 方向映射(`directionCount` 决定方向数,`framesPerDirection` 决定每方向帧数): - **八方向(默认,`directionCount=8`)**: - 索引 0-1: up / 2-3: down / 4-5: left / 6-7: right - 索引 8-9: up-right / 10-11: down-right / 12-13: up-left / 14-15: down-left - 索引 16: idle - **四方向(`directionCount=4`,兼容旧布局)**: - 索引 0-1: up / 2-3: down / 4-5: left / 6-7: right / 8: idle > 斜向由移动向量按角度量化(每 45° 一档)得到;键盘 WASD 两键同按(如 W+D)即为斜向。 ### Core / CameraController.ts 摄像机跟随组件,独立于玩家控制器。 | 属性 | 类型 | 说明 | |------|------|------| | `target` | `Node` | 跟随目标节点 | | `offset` | `Vec2` | 偏移量 | | `smoothSpeed` | `number` | 平滑跟随速度 | | `bounds` | `Rect` | 摄像机边界锁定(可选) | | 方法 | 说明 | |------|------| | `follow(target)` | 设置跟随目标 | | `shake(intensity, duration)` | 屏幕震动(预留) | ### Core / EventBus.ts 全局事件总线,模块间通过事件通信,不直接耦合。 ```typescript EventBus.on(eventName, callback, target); EventBus.off(eventName, callback, target); EventBus.emit(eventName, data); ``` ### Core / GameManager.ts 游戏启动脚本,串联所有系统。是 Demo 的入口点。 | 属性 | 类型 | 说明 | |------|------|------| | `playerPrefab` | `Prefab` | 玩家预制体 | | `enemyPrefab` | `Prefab` | 敌人预制体 | | `playerSpawnPosition` | `Vec3` | 玩家出生位置 | | `enemyCount` | `number` | 敌人生成数量 | | `enemySpawnRadius` | `number` | 敌人分布半径 | | `attackRange` | `number` | (已废弃)近战命中结算已下沉到 `PlayerController.meleeRange` | | `pickupRange` | `number` | 物品拾取检测范围 | **核心流程**: ``` onLoad → 初始化 ItemFactory → 注册事件监听 start → 生成玩家 + 生成敌人 → 设置摄像机 事件驱动: PLAYER_ATTACK → 命中结算在 PlayerController(挥击开始 / 命中两种载荷),GameManager 不再处理 PLAYER_INTERACT → 拾取物品 / 开关背包 / 暂停 ITEM_DROPPED → 在地图生成物品节点 ENTITY_DIED → 按掉落表生成掉落物 ``` ### Life / BaseLife.ts 生命体基类,继承 BaseEntity。代表所有会移动、有生命值、会消耗的活物。 | 属性 | 类型 | 说明 | |------|------|------| | `baseMoveSpeed` | `number` | 基础移动速度 | | `direction` | `Vec2` | 当前移动方向 | | `isMoving` | `boolean` | 是否正在移动 | | `attackValue` | `number` | 基础攻击力 | | `maxHealth` | `number` | 最大生命值 | | `maxHunger` | `number` | 最大饱食度 | | `maxThirst` | `number` | 最大口渴值 | | `hungerDecreaseRate` | `number` | 饱食度每秒衰减 | | `thirstDecreaseRate` | `number` | 口渴值每秒衰减 | | `currentHealth` | `number` | 当前生命值 | | `currentHunger` | `number` | 当前饱食度 | | `currentThirst` | `number` | 当前口渴值 | | `equipmentItems` | `BaseItem[]` | 装备栏物品 | | `holdingItems` | `BaseItem[]` | 手持物品栏 | | 方法 | 说明 | |------|------| | `attack(target: BaseLife)` | 攻击目标,触发 CombatManager 计算伤害 | | `getAttackDamage(): number` | 计算基础攻击力 + 装备加成 | | `getDefense(): number` | 计算防御力(装备加成) | | `takeDamage(damage)` | 受到伤害,触发 `onTakeDamage` 钩子 | | `onScheduledTick()` | 每秒扣减饱食度/口渴值,不足时扣血 | | `update(dt)` | 移动逻辑 | > 使用物品的入口在 `Inventory.useItem`(→ `BaseItem.onUse` → `CombatManager.applyEffect`,按物品 `effects` 类型分别恢复三围);基座曾有一个把三围按同一数值同时恢复的 `BaseLife.useItem` 死代码,已于 2026-09-03 删除(零调用、语义误导)。 ### Life / PlayerController.ts 玩家输入控制组件,附加到玩家节点上,通过键盘控制角色。 | 按键 | 功能 | |------|------| | WASD / 方向键 | 移动 | | 空格 / J | 攻击(近战命中由 PlayerController 在攻击动画结束时自行结算) | | Shift | 冲刺/加速(走 BaseLife 的 DASH 事件链) | | E | 拾取/交互 | | Q | 丢弃当前手持物品 | | I | 开关背包(打开时锁定玩家操作,I / ESC 仍可用) | | 数字键 1-9 | 使用热键栏物品 | | ESC | 关闭面板 / 暂停钩子 | ### Life / EnemyAI.ts 敌人 AI 组件,有限状态机实现。 | 属性 | 类型 | 说明 | |------|------|------| | `moveSpeed` | `number` | 追击移动速度 | | `patrolSpeed` | `number` | 巡逻移动速度 | | `detectionRange` | `number` | 索敌范围 | | `attackRange` | `number` | 攻击范围 | | `damage` | `number` | 攻击力 | | `attackCooldown` | `number` | 攻击冷却时间 | | `patrolRadius` | `number` | 巡逻半径 | **状态机流程**: ``` Idle → Patrol → Chase → Attack → (循环或回Patrol) ↑ | └──── 超出范围 ───────┘ ``` ### Item / BaseItem.ts 物品基类,继承 BaseEntity。物品有三种状态: ``` Inventory (背包中) Placed (地图上) Equipped (装备中) ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ 纯数据,无节点 │ │ 有节点,可显示 │ │ 附加到装备栏, │ │ 无动画 │ │ 可有动画 │ │ 提供属性加成 │ │ 由 Inventory 管理 │ │ 可被拾取/交互 │ │ 消耗耐久度 │ └─────────────────┘ └─────────────────┘ └─────────────────┘ ``` | 属性 | 类型 | 说明 | |------|------|------| | `itemType` | `ItemType` | 物品类型(Consumable/Weapon/Armor/Material) | | `itemState` | `ItemState` | 当前状态(Inventory/Placed/Equipped) | | `maxDurability` | `number` | 最大耐久度 | | `durabilityDecreaseRate` | `number` | 耐久度每秒衰减 | | `currentDurability` | `number` | 当前耐久度 | | `stackable` | `boolean` | 是否可堆叠 | | `maxStack` | `number` | 最大堆叠数 | | 方法 | 说明 | |------|------| | `onUse(user: BaseLife)` | 使用物品(消耗品回属性,装备自动装备) | | `onEquip(user: BaseLife)` | 装备时回调 | | `onUnequip(user: BaseLife)` | 卸下时回调 | | `onPickup()` | 被拾取时回调 | | `onDrop()` | 被丢弃时回调 | | `onScheduledTick()` | 每秒扣减耐久度,耗尽触发 `onDeath` | ### Item / Inventory.ts 背包系统,管理物品的存储、堆叠、热键栏、装备栏。 | 属性 | 类型 | 说明 | |------|------|------| | `inventorySize` | `number` | 背包格子数 | | `hotbarSize` | `number` | 热键栏格子数(默认9) | | 方法 | 说明 | |------|------| | `addItem(itemId, quantity)` | 添加物品到背包(自动堆叠/找空位) | | `removeItem(slot, quantity)` | 从背包移除物品 | | `hasItem(itemId)` | 检查是否拥有某物品 | | `getItemInHand()` | 获取当前手持物品 | | `equipItem(slot)` | 装备物品 | | `unequipItem(slot)` | 卸下物品 | | `useItem(slot, user)` | 使用物品 | | `moveToHotbar(slotIndex, hotbarIndex)` | 移到热键栏 | | `saveInventory()` / `loadInventory()` | 存档/读档 | ### Item / ItemFactory.ts 物品工厂,从配置模板创建物品实例。 ```typescript // 物品类型枚举(4 类;下文「食物/饮品/药品」等是玩法侧人为分类,非枚举) enum ItemType { CONSUMABLE, WEAPON, ARMOR, MATERIAL } // 物品效果接口 interface ItemEffect { type: 'health' | 'hunger' | 'thirst' | 'speed' | 'damage' | 'defense'; value: number; duration?: number; } // 物品模板接口 interface ItemTemplate { id: string; name: string; description: string; type: ItemType; maxDurability: number; durabilityDecreaseRate: number; stackable: boolean; maxStack: number; effects: ItemEffect[]; // 武器/防具专用 attackBonus?: number; defenseBonus?: number; } ``` ### World / BaseDestructible.ts 可破坏物体基类,继承 BaseEntity。代表地图上可以被破坏/采集的静态物体(建筑、树木、矿石等)。 **不包含移动、饥饿/口渴等功能**,与 BaseLife 区分。 **能力**:血量/防御/受击冷却、头顶血条 HUD、概率掉落、渐进破坏阶段、修复、事件广播、网络同步钩子。 | 属性 | 类型 | 说明 | |------|------|------| | `maxHp` | `number` | 最大血量 | | `currentHp` | `number` | 当前血量 | | `defense` | `number` | 防御力(从伤害中扣除) | | `damageCooldown` | `number` | 相邻两次受击最小间隔(秒),0 表示无冷却 | | `dropTable` | `DropTableEntry[]` | 掉落物品配置(itemId + 数量区间 + 概率) | | `destructionStages` | `number` | 破坏阶段数,1 表示无渐进表现 | | `hpBar` / `hpText` | `ProgressBar` / `Label` | 头顶血条引用(CC 编辑器拖拽绑定) | | 方法 | 说明 | |------|------| | `takeDamage(damage, source?)` | 受到伤害(防御减伤 + 冷却 + `ENTITY_DAMAGED` 广播),血量归零触发 `onDeath` | | `repair(amount)` | 修复物体,恢复 HP(上限 maxHp),触发 `ENTITY_REPAIRED` | | `onHarvest(source?)` | 被采集时回调(砍树/挖矿),掉装备并销毁(已修复双重掉落) | | `onDeath(source?)` | 被摧毁,触发掉落 + `ENTITY_DIED` / `ENTITY_DESPAWNED` 广播 + 销毁节点 | | `dropLoot()` | 按掉落表概率生成掉落物,发射 `LOOT_DROPPED` 事件 | | `onStageChanged(stage)` | 渐进破坏阶段回调,随血量降低切换贴图/特效(子类重写) | | `onStateChanged(reason)` | 网络同步钩子(`'damage' \| 'death' \| 'harvest' \| 'repair'`),子类重写 | **事件广播**: | 事件 | 触发时机 | |------|---------| | `ENTITY_DAMAGED` | 受到伤害 | | `ENTITY_DIED` | 死亡 / 被采集 | | `ENTITY_DESPAWNED` | 节点销毁前 | | `ENTITY_REPAIRED` | 修复时 | **掉落表配置**(子类在代码中设置,或在编辑器中通过数组配置): ```typescript this.dropTable = [ { itemId: "wood", minQuantity: 2, maxQuantity: 5, probability: 1.0 }, // 必掉 { itemId: "seed", minQuantity: 1, maxQuantity: 2, probability: 0.3 }, // 30% 概率 ]; ``` ### World / Harvestable.ts 可采集物 — `BaseDestructible` 的最小具体化(2026-09-03 新增)。按类型内置默认掉落表,玩家按 E 交互(或攻击摧毁)后直接产出对应材料/食物并销毁,让材料类物品在 demo 中有真实来源。 | 属性 | 类型 | 说明 | |------|------|------| | `variant` | `HarvestableType` | 类型:`tree`(树→木材+苹果)/ `rock`(岩石→石头+铁矿石)/ `bush`(草丛→纤维+浆果)/ `fishing_spot`(鱼点→生鱼) | | `dropTable`(继承) | `DropTableEntry[]` | 未显式配置时按 `variant` 自动填充类型默认表 | **接入方式**:`GameManager.spawnHarvestables()` 在出生点外围生成(`harvestableCount` 可配,默认 8);玩家靠近按 E,`GameManager.tryHarvest` 在"无可拾取物品"时调用 `onHarvest` 产出掉落并销毁。 ### World / WorldManager.ts 世界管理,负责地图上所有动态实体的生成、销毁和掉落管理。 | 方法 | 说明 | |------|------| | `registerEntity(entity)` | 注册实体到世界(键用 `uid`,避免同名节点/同模板掉落物互相覆盖;广播 `ENTITY_SPAWNED`) | | `unregisterEntity(entity)` | 注销实体(死亡/销毁时调用,清理注册表;广播 `ENTITY_DESPAWNED`) | | `getEntityById(id)` | 按 `uid` 查找实体 | | `getEntitiesInRange(position, range)` | 获取范围内实体(O(n) 遍历,见下方空间索引优化项) | | `getLivesInRange(position, range)` | 获取范围内生命体(`BaseLife` 过滤,索敌/攻击用) | | `dropLoot(position, itemId, quantity)` | 在位置生成掉落物(随机偏移防重叠,注册到世界) | | `clearAll()` | 清空全部实体 + 事件总线(场景切换用) | ### Combat / CombatManager.ts 战斗管理,处理伤害计算、装备加成、命中判定。 ```typescript class CombatManager { static calculateDamage(attacker: BaseLife, target: BaseLife): number { // 基础攻击力 + 装备攻击加成 - 目标防御力 - 装备防御加成 // 最低保底伤害 1 } static heal(target: BaseLife, amount: number): void { // 恢复生命值,不超过 maxHealth } static applyEffect(target: BaseLife, effect: ItemEffect): void { // 应用物品效果(恢复/增益/减益) } } ``` ### Network / 联机系统(客户端核心 Phase 4.1 ✅,服务器与 demo 待宿主 Phase 4.2) **分层设计(核心约束:纯逻辑核心与平台传输解耦)**: | 层 | 文件 | 依赖 | 职责 | |----|------|------|------| | 协议核心 | `NetProtocol.ts` | **零依赖(纯 TS)** | 消息信封 `{t,s,d}`、类型常量、编解码 | | 状态序列化 | `NetState.ts` | **零依赖** | 实体→网络状态(**uid** 作网络 ID)、自身上行去抖、快照 diff | | 传输适配器 | `NetTransport.ts` | 仅全局 WebSocket | 连接抽象:WebSocket 实现(CONNECTING 排队/onOpen)+ 进程内 Loopback(测试) | | 同步核心 | `NetSyncCore.ts` | 仅 GameEvents(纯 TS) | 本地事件→上行映射、远程事件→本地应用、快照→幽灵 | | 联机组件 | `NetworkSync.ts` | cc(薄接线) | 生命周期、EventBus 桥、周期上行、幽灵实体、表现钩子 | **设计考量(承接 EventBus 事件驱动)**:所有实体状态变更经 EventBus 派发,网络层监听事件做同步——`NetSyncCore.mapOutboundEvent` 把本地事件映射为可上行的 uid/坐标/数值负载,`applyRemoteEvent` 把远程事件血量权威化 + 表现层通知。 **差异约束(与宿主验证宿主的协同约定,host 开发必读)**: - 协议 / 序列化 / 同步核心**纯 TS、零 cc import** → 宿主无头测试直接加载,验证的就是交付代码本身(仓库自带自检 `tools/net-selfcheck.ts`,47 项断言(汇总行自报计数,P4-3 澄清))。 - 传输层只用**标准 WebSocket**(CC 浏览器 / 原生 / 微信小程序均提供全局 WebSocket)→ 宿主浏览器端**零 shim 改动**(浏览器原生 WebSocket)。 - **服务器端不属于游戏脚本**(房间 / 广播 / 权威结算),由宿主在其仓库实现(扩展其 `serve.mjs` 或旁挂 ws server);游戏脚本只含客户端网络代码。 - 微信小程序专属 API(`wx.connectSocket` / RTC 联机对战引擎)只允许在 `NetTransport` 的薄适配器做分支,不得扩散到核心。 **v1 同步模型:客户端权威-lite(服务器中继 + 幽灵同步)** - 每个客户端照常跑完整本地逻辑(**单机代码零改动**),把自己状态(位置/血量)以 `syncRate` Hz 上行; - 服务器只做 JOIN 分配 uid、中继 STATE→SNAPSHOT、转发 EVENT; - 其它玩家在本地以**幽灵实体**呈现(NetworkSync 生成,宿主渲染形象),SNAPSHOT 驱动生成/位移/销毁; - 本地游戏事件(攻击/伤害/死亡/丢弃/拾取/掉落)经 EventBus 桥上行 → 服务器转发 → 其它客户端血量权威化 + 表现; - **网络 uid 与本地实体 uid 统一(P4-4,2026-09-03)**:本地玩家的 WorldManager 注册键是 `BaseEntity.uid`(`Entity_N`,实例自增),网络身份是服务器分配的 `U_N` —— `NetworkSync.resolveEntity` 先按 `_myUid` 把 `U_N` 映射到本地玩家,再查共享实体/幽灵。这样**服务器权威事件(如敌人攻击玩家 `entity:damaged` targetUid=U_N)能走游戏自身管线** `applyRemoteEvent → applyHp` 覆盖本地血量(此前会静默落空,宿主需自同步补丁绕行);`spawnGhost` 同时防御跳过本机 uid 的回显快照,避免给自己造幽灵。 - **已知限制**: - 共享敌人血量各端独立演算可能分叉、敌人击杀掉落物不跨端同步 —— **已由宿主解决(Phase 4.2/4.3)**:服务器权威共享敌人(血量/死亡/掉落全服一致),玩家攻击敌人/敌人攻击玩家都走权威血量覆盖(依赖上述 P4-4 uid 统一)。 - **只共享敌人,采集物与玩家私有掉落仍各端独立(确认设计边界)**:`Harvestable`(树/岩石/草丛/鱼点)与玩家私有掉落(Q 键丢弃等)仍是各端自己的实例;共享敌人掉落的拾取是"服务器广播 → 各端各建一份真实掉落物,谁先捡谁得,拾取经 `ITEM_PICKED_UP` 广播让其它端清除本地副本"。若后续做"全共享世界",这是下一个演进点。 **消息协议(`NetProtocol.ts` 定义,服务器按此实现)**: - 信封:`{ t: 类型, s: 序号, d: 负载 }`,JSON 文本帧;序号发送方单调递增。 - 客户端→服务器: - `join` `{ name, version }` - `leave` `{ uid?, reason? }` - `state` `{ uid, pos:{x,y}, dir:{x,y}, moving, hp, maxHp }`(周期性,去抖) - `action` `{ uid, act, data }`(act ∈ `attack/interact/drop/use`,NetAction) - `event` `{ ev, data }`(ev 为 GameEvents 值,data 只含 uid/坐标/数值) - 服务器→客户端: - `welcome` `{ uid, players:[{uid,name}], seed? }` - `snapshot` `{ frame, full?, entities: NetEntityState[] }`(中继其它玩家 state) - `event2c` `{ sender, ev, data }`(转发的事件) - `leaved` `{ uid, reason? }` - 实体网络状态 `NetEntityState`:`{ uid, kind, entityId, pos:{x,y}, hp?, maxHp?, facing?, moving?, name? }` - ⚠️ **uid 是网络实体 ID**(BaseEntity 实例唯一),`entityId` 只是类型/业务标识(如物品模板 id)——同模板多实体靠 uid 区分。 **出站广播事件(其余为 UI 本地 / 暂不同步)**:`PLAYER_ATTACK`(仅挥击)/ `ENTITY_DAMAGED` / `ENTITY_DIED` / `ITEM_DROPPED` / `ITEM_PICKED_UP` / `LOOT_DROPPED`。 **客户端接入(CC 编辑器 / 宿主装配)**: 1. 场景建空节点挂 `NetworkSync` 组件;填 `serverUrl`(默认 `ws://127.0.0.1:8080/ws`)、`autoConnect`、`syncRate`; 2. `localPlayerNode` 绑定玩家节点(不绑则自动从 WorldManager 找 `isPlayer` 实体); 3. 可选钩子(代码赋值):`onRemotePlayerSpawn(ghost,state)` / `onRemoteEntityDespawn(uid)` / `onRemoteEvent(kind,payload)` / `onConnectionChange(state,info)`; 4. 单机不受影响:未连接时组件全空转(不注册监听、不发消息)。 **宿主待办(Phase 4.2,按本节协议实现)**: - WebSocket 服务器:接 JOIN→分配 uid;STATE→定时组 SNAPSHOT 广播;EVENT 转发给其它客户端;LEAVE 处理; - 浏览器端联机 UI:输入服务器地址 → 双窗口同屏验证位置/攻击/掉落同步(幽灵玩家渲染用 `onRemotePlayerSpawn`); - 无头测试:用 `LoopbackTransport`(或内存假服务器)验证协议往返与事件映射;组件级测试可用 `NetworkSync.pairLoopback(other)` 双实例互联。 --- ## 物品状态生命周期 ``` ┌──────────────┐ │ ItemFactory │ │ (配置模板) │ └──────┬───────┘ │ ┌──────▼───────┐ ┌───│ Placed(地图) │◄──── 生成/掉落 │ └──────┬───────┘ │ │ 按 E 拾取 │ ┌──────▼───────┐ │ │ Inventory │◄──── 背包 │ │ (背包中) │ │ └──┬──────┬────┘ │ │ │ │ │ │ 装备 │ │ 使用 ▼ │ │ ┌──────────┐ │ │ │ Equipped │◄──── 装备栏 │ │ │ (装备中) │ │ │ └─────┬────┘ │ │ │ 卸下 │ │ │ │ │ 丢弃 │ │ └───┬────┘ │ │ └──────────┘ (回到地图) ``` --- ## 当前进度(2026-08-06) ### 主干基线快照(2026-09-03,稳定冻结) - **基线**:`12ef258`(P5-1 采集物无限掉落修复 + 首个通用系统插件 `extensions/runtime-assets`)。 - **基座**:20 个 TS 文件,Phase 1 核心 + 全部已记录修复 + Phase 4.1 联机客户端核心 + P4-4 + **P5-1**;宿主 109 项无头断言(Phase 4.2/4.3 联机全链路,含 P4-4/P5-1 回归)+ 网络核心 47 项自检全绿。 - **玩法**:22 种物品 / 4 类采集物(`Harvestable`)/ 敌人两级掉落 / 装备属性加成已闭环(详见下各小节)。 - **插件层**:`extensions/` 已有 4 个插件——`runtime-assets`(通用资产管线,槽位约定 / 精灵状态机 / `AssetProvider` 接口)+ `crafting`(合成,鸭子类型背包 + 原子合成)+ `saving`(存档,版本化快照 + 注入式读写)+ `buff`(状态效果,三种堆叠策略 + DOT),均纯 TS 核心 + 自带 selfcheck(见 extensions/README)。 - **之后**:主干只收关键 bug 修复 + L0 配置增补;玩法与架构改动走 §开发策略 的 L1~L3 路径。 ### 当前状态与后续规划(2026-09-03) **已完成闭环**:Phase 1 核心 + Demo 逻辑 + 22 物品 / 采集 / 装备加成 + 联机客户端核心(Phase 4.1)与 P4-1/2/3/4 修复 + **P5-1 采集物无限掉落修复** + 插件层 4 个插件(`runtime-assets` / `crafting` 合成 / `saving` 存档 / `buff` 状态效果);全部玩法可在宿主可视化试玩与无头验证(115 项断言 + 插件层 72 项自检/集成全绿)。 **后续规划(按优先级)**: 1. **插件化推进(L3)**:`crafting` / `saving` / `buff` 已落地;接下来按 §玩法丰富方向 做 建造(网格放置 + `Building`)/ 地图生成 等自包含插件;`Harvestable` 迁入 `extensions/harvesting/` 因改冻结主干需走分支评审,延后; 2. **美术 / 音效接入**:按 `runtime-assets` 槽位约定(`<元素>/<时机>[/方向]` + 索引帧 `0.png…`)填图,上层自动替换色块——游戏侧只遵守约定、不碰上层实现; 3. **Phase 2 CC 编辑器集成**(作者回归后):导入编辑器建场景跑通完整 Demo;宿主已先行验证逻辑等价; 4. **玩法深化(L0/L1)**:更多物品 / 敌人 / Boss / 波次、合成、建造、存档(见 §待优化方向 / §玩法丰富方向); 5. **联机演进**:客户端平滑插值、断线重连、服务器权威化进一步推进(Phase 4 遗留)。 6. **内容配置化 + 插件隔离 + 玩法蓝图**(2026-09-04):内容进配置文件、插件隔离契约强化、28 项玩法评估留档——见 §内容配置化 / §插件隔离与收敛 / §玩法丰富方向·玩法蓝图评估。 ### 已完成 ✅ — Script 架构层(Phase 1 完成) Phase 1 收尾时 15 个 TypeScript 文件全部编写完成,导入路径一致,类继承关系正确(当前 20 个:+ Network 五件 [Phase 4.1] + `World/Harvestable`)。 | 模块 | 文件 | 状态 | |------|------|------| | Core | BaseEntity / BaseAnimation / EventBus / CameraController / GameManager | ✅ 完成 | | Life | BaseLife / PlayerController / EnemyAI | ✅ 完成 | | Item | BaseItem / Inventory / ItemFactory | ✅ 完成 | | World | BaseDestructible / WorldManager | ✅ 完成 | | Combat | CombatManager | ✅ 完成 | | Network | NetProtocol / NetState / NetTransport / NetSyncCore / NetworkSync | ✅ 完成(客户端核心 Phase 4.1;服务器 Phase 4.2 待宿主) | ### 已完成 ✅ — Demo 逻辑完善(Phase 1 收尾) | 功能 | 实现方式 | |------|---------| | 玩家攻击 → 找目标打伤害 | `PlayerController` 在攻击动画结束时通过 `WorldManager.getLivesInRange` 查找最近敌人,调用 `BaseLife.attack()`(GameManager 不再处理攻击,修复了事件递归双结算) | | 敌人自动索敌 | `EnemyAI` 通过 `WorldManager.getLivesInRange` 自动查找玩家,目标丢失后自动重搜 | | E 键拾取 | `GameManager.handlePickup` 检测附近 `ItemState.PLACED` 物品,加入背包后销毁节点 | | Q 键丢弃 | `GameManager.handleDropItem` 在玩家位置创建物品节点,随机偏移防重叠 | | 游戏初始化 | `GameManager` 初始化 `ItemFactory`、生成玩家和敌人、设置摄像机、给初始物品 | | 死亡掉落 | `GameManager` 监听 `ENTITY_DIED` 事件,按掉落表生成掉落物(`WorldManager.dropLoot`) | | 玩家复活 | 玩家死亡 3 秒后自动复活,重置属性回出生点 | | 可破坏物体基类完善 | `BaseDestructible` 修复采集双重掉落 bug,新增血条 HUD / 渐进破坏阶段 / 修复 / 事件广播 / 网络同步钩子 | ### 已完成 ✅ — Bug 修复(2026-09-02) | 问题 | 修复 | |------|------| | 实体无唯一 ID,同名字节点/同模板掉落物在 `WorldManager` 注册表互相覆盖 | `BaseEntity` 构造时自动分配 `uid`(Entity_N 自增),注册表键改用 `uid` | | `createEnemyNode` 兜底路径只挂 BaseLife,敌人无 AI 不动 | 补挂 `EnemyAI` + `BaseAnimation` | | 物品使用只有消耗没有效果(effects 未复制、onUse 空壳) | `ItemFactory.createItem` 复制 `effects`;`BaseItem.onUse` 消费效果调 `CombatManager.applyEffect`;`onUse/onPickup/onDrop` 改 public 供跨组件调用 | | 热键栏恒空,数字键 1-9 全部失效;无背包直用路径 | `giveStarterItems` 开局填充热键栏前 3 格;`Inventory` 新增 `useSlotDirectly` 供背包 UI 直用 | | 站立攻击永远挥空(P2-1):攻击动画每帧被 `setMoving(false)` 重置,`resolveAttackHit` 永不触发 | `setMoving`/`setDirection` 在 one-shot 播放期间短路(`if (this.isOneShot) return`) | > 遗留:`ItemEffect` 的 speed/damage/defense 临时 buff 仍为占位(Phase 3 buff 系统)。装备属性加成(attackBonus/defenseBonus)已于 2026-09-03 接通(见下)。`BaseLife.useItem` 死代码已于 2026-09-03 删除(见 §Life/BaseLife)。 ### 已完成 ✅ — Bug 修复(2026-09-03) | 问题 | 修复 | |------|------| | Q 键无限刷物品(P3-1):热键栏幽灵条目 + 无条件 emit,背包空后每按一次 Q 凭空生成 1 个地面物品 | `PlayerController.dropItem` 仅 `removeItem` 真正扣减成功才 `emit ITEM_DROPPED`(防御:丢弃未发生禁止凭空生成);`Inventory.getItemInHand` 跳过幽灵条目(fall-through 到下一真实热键栏项);`removeItem/useItem` 物品耗尽时经 `clearHotbarGhost` 清幽灵条目(背包仍有同 id 堆叠则保留热键栏偏好);顺带修 `moveToHotbar` 交换路径把热键栏 qty=1 写回背包导致的数量损坏/凭空造物 | > 验证(宿主):热键栏真实物品丢尽后 Q 自动停止;背包全空后 Q 连按 10 次地上物品数不变。回归断言已固化进宿主 `tests/headless.mjs` 第 6 节(Q 丢弃回归 P3-1)。 ### 已完成 ✅ — Bug 修复:采集物可被原地无限采集(2026-09-03) **问题**:站在同一采集物(树/岩石/草丛/鱼点)旁反复按 E,每按一次都会再掉一坨物品——**原地无限刷**。根因: - `BaseDestructible.onHarvest` 掉落并 `destroySelf()` 销毁节点后,**既没有把 `currentHp` 置 0,也没有从 `WorldManager` 注销**; - 而 `GameManager.tryHarvest` 的采集判定只看 `entity instanceof Harvestable && entity.currentHp > 0`,`getEntitiesInRange` 也仍会返回注册表里这个已销毁实例; - 于是同一实例被反复采集 → 每次 E 都重新走 `onHarvest → dropLoot` → 无限掉落。 **修复(双保险)**: | 位置 | 改动 | |------|------| | `World/BaseDestructible.onHarvest` | 采集即把 `currentHp = 0`,使 `tryHarvest` 的 `currentHp > 0` 守卫生效(任何直接调 `onHarvest` 的路径都被拦住) | | `Core/GameManager.tryHarvest` | 采集前先 `worldMgr.unregisterEntity(entity)` 注销,杜绝残留实例被 `getEntitiesInRange` 反复命中(兜底防泄漏) | **验证**:采集树→掉 3 木→全部拾空→原地再按 E 不再掉落;连续按 E 不再累积;世界注册表无已销毁残留实体。回归断言已固化进宿主 `tests/headless.mjs` 第 8 节。 ### 已完成 ✅ — 多方向移动升级(2026-09-02) 位移本身早已支持斜向(WASD 两键同按 → 归一化向量),本次把**动画朝向**从 4 方向升级为 8 方向: | 改动 | 说明 | |------|------| | `BaseAnimation` 新增 `directionCount` | 4/8 可选,默认 8;`4` 完全兼容旧四方向布局 | | `setDirection` 角度量化 | 每 45° 一档,新增 4 个斜向(up-right / up-left / down-right / down-left) | | `getFrameIndex` 方向序号化 | 方向起始帧 = 方向序号 × `framesPerDirection`,顺带修复旧硬编码 baseIndex 只对 `framesPerDirection=2` 正确的隐患 | | 触屏摇杆(验证宿主) | 8 扇区,斜向同时按两键(如右上 = W+D) | | 无头测试(验证宿主) | 攻击断言改为等动画播完(0.4s)再判定;当前 64 项断言全绿(含 P3-1 Q 丢弃回归、采集闭环、装备加成、联机组件) | ### 已完成 ✅ — 物品种类扩充(2026-09-03) 物品模板从 6 种扩充到 **22 种**,覆盖全部 4 个 `ItemType`,并接入敌人掉落表与开局物品(宿主图标已按 itemId/类型兜底,配好模板即生效,无需宿主改动): | 类别 | 物品(新增加粗) | 效果 / 加成 | |------|----------------|------------| | 食物 | 面包 / **苹果** / **浆果** / **生鱼** / 牛排 | 回饱食度(浆果/牛排附带少量回血) | | 饮品 | 矿泉水 / **牛奶** | 回口渴值(牛奶附带回血) | | 药品 | 绷带 / **生命药水** / **急救包** | 回血 30 / 50 / 80(强度分档) | | 武器 | **匕首** / **长弓** / 铁剑 / **战斧** / **战锤** | 攻击 +3 / +4 / +5 / +7 / +9 | | 防具 | **布衣** / 皮甲 / **铁甲** | 防御 +1 / +3 / +6 | | 材料 | **木材** / **石头** / **铁矿石** / **植物纤维** | 无效果(供后续合成/建造),可堆叠 | > 遗留:`ItemEffect` 的 speed/damage/defense 仍为占位空实现(Phase 3 buff 系统),新消耗品统一使用 health/hunger/thirst。 ### 已完成 ✅ — 掉落/采集闭环:22 种物品全部可获取(2026-09-03) 初始扩充时 11 种新模板只注册在 `ItemFactory`、demo 拿不到;本次补齐全部获取途径: | 获取途径 | 覆盖物品 | |---------|---------| | 开局物品 | 面包 / 水 / 绷带 / 苹果 / 木材 / 石头 / 铁剑 / 皮甲 | | 普通敌人掉落 | + 浆果 / 纤维 / 牛奶(面包掉率保持 0.6,宿主无头测试固定 `Math.random()=0.5` 的确定性断言不受影响) | | 精英敌人掉落(约 20%) | + 牛排 / 生鱼 / 生命药水 / 急救包 / 匕首 / 长弓 / 战斧 / 战锤 / 布衣 / 铁甲 / 铁矿石 | | 可采集物 `Harvestable` | 树→木材+苹果、岩石→石头+铁矿石、草丛→纤维+浆果、鱼点→生鱼 | > 敌人按 `EnemyAI.tier` 分级(normal / elite,精英血量/攻击/移速更高),掉落表为模块级常量 `NORMAL/ELITE_ENEMY_DROPS`,改配置即可调掉落;E 键在无可拾取物品时回退为采集(`GameManager.tryHarvest`)。 > 验证:宿主无头测试全绿(含图标自检:22 种全配专用图标、覆盖全部 4 个 ItemType);确定性脚本复验树/岩石/草丛/鱼点产出与精英掉落表,全程无 error。 ### 已完成 ✅ — 联机客户端核心(Phase 4.1,2026-09-03) 按"差异约束"分层实现 `Network/` 五个文件(详见 §Network),游戏侧只含客户端网络代码,单机零改动、不受影响: | 文件 | 内容 | 验证 | |------|------|------| | `NetProtocol.ts` | 消息信封/类型/编解码(纯 TS) | 自检:往返/非法输入 | | `NetState.ts` | 实体序列化(**uid** 作网络 ID)、去抖、快照 diff(纯 TS) | 自检:kind 推断/去抖/diff | | `NetTransport.ts` | 传输抽象 + WebSocket + Loopback(纯 TS) | 自检:双端互联/断开传播 | | `NetSyncCore.ts` | 出站事件映射、远程事件/快照应用(纯 TS) | 自检:出站 8 项/入站 5 项/快照 4 项 | | `NetworkSync.ts` | 联机组件(cc 薄接线):周期上行/EventBus 桥/幽灵实体/表现钩子 | 宿主 shim 编译通过 | > 修复点:原 `NetworkSync.serializeEntity` 用 `entityId` 作网络 ID(会与同模板多实体冲突),已改为 `uid`;`initEventListeners` 空壳改为 EventBus 桥,事件清单收敛为 6 个可广播事件。 > 自检:`tools/net-selfcheck.ts` 47 项断言全绿(汇总行自报计数,P4-3 澄清)(位于 `_BaseClassScript` 之外,CC 不编译);`NetworkSync.ts` 经宿主 cc shim 打包验证通过。 > 待宿主(Phase 4.2):WebSocket 服务器、浏览器双窗口联机 demo、无头组件级测试(协议契约见 §Network)。 ### 已完成 ✅ — 联机修复(P4-1 关键 / P4-2 小,2026-09-03) 按主干冻结策略(关键 bug 修复直接入主干)修复宿主报告的 2 个问题: | 编号 | 问题 | 根因 | 修复 | |------|------|------|------| | **P4-1 关键** | 真实 WebSocket 下 JOIN 被丢弃,联机完全不可用 | `NetworkSync.connect()` 在 `transport.connect()` 后立即发 JOIN,此刻真实 WebSocket 处于 CONNECTING,`send()` 因 `!ready` 丢弃且无补发(Loopback 同步 open + pairLoopback 手动置 `_connected` 掩盖) | ① `NetTransport` 增加 `onOpen` 回调;② `WebSocketTransport.send()` 在 **CONNECTING 期间排队、open 后自动 flush**(不丢任何早期消息);③ `NetworkSync.connect()` 改为经 `onTransportOpen()` 在连接建立后发送 JOIN + 补一帧初始 STATE(`_joinSent` 防重复;同步建连走 `if (transport.ready)` 立即补发) | | **P4-2 小** | STATE 去抖对位置无效,移动时全速刷屏 | `serializeEntity` 只对 hp 取整,`pos.x/y` 原始浮点 → 每帧微变,`StateCache.changed` 几乎恒 true | `NetState.serializeEntity` 对 `pos.x/y` **取整**(像素单位):静止时位置稳定→不上行,移动时按整像素变化→受 `syncRate` 限速 | | **P4-3 文档** | 自检计数疑似不准 | 误报 | 澄清:README"38 项"与实际**38 个 `check()` 调用一致**(`grep -c "check("` 的 39 含函数定义行);并把自检汇总行改为**自报断言总数**,杜绝再脱节 | > 附带优化:`pushState` 上行 STATE 的 `uid` 改用服务器分配的 `_myUid`(未分配前回退本地实体 uid),对齐协议契约 `state { uid, ... }`。 > 自检:新增 WebSocket 建连/排队 7 项 + pos 取整 1 项,**47 项断言全绿**;`NetworkSync.ts` 经宿主 cc shim 打包验证通过。 ### 已完成 ✅ — 联机修复(P4-4 关键:网络 uid 与本地实体 uid 统一,2026-09-03) 按主干冻结策略(关键 bug 修复直接入主干)修复宿主报告的遗留问题(根因在游戏侧): | 编号 | 问题 | 根因 | 修复 | |------|------|------|------| | **P4-4 关键** | 服务器→玩家的伤害无法走游戏自身管线:`entity:damaged`(targetUid=本机网络 `U_N`)经 `applyRemoteEvent → resolveEntity` 静默落空,玩家不掉血(宿主此前用 `server-enemy.ts` 自同步补丁绕行) | 本地玩家注册进 WorldManager 用 `BaseEntity.uid`(`Entity_N`,每浏览器实例自增),而网络身份是服务器分配的 `U_N`;`resolveEntity` 先查 WorldManager 再查幽灵,永远无法用 `U_N` 命中本地玩家 | ① `NetworkSync.resolveEntity` 先按 `_myUid` 把网络 uid 映射到本地玩家(防御性补 `_ensureLocalPlayer`)→ 服务器权威伤害/血量覆盖走 `applyRemoteEvent → applyHp` 自身管线;② `spawnGhost` 防御跳过本机 uid 的回显快照(当前中继只发 others,纯兜底);宿主的自同步补丁已删(见宿主仓库) | | **P4-4 清理** | `BaseLife.useItem` 死代码(零调用,且"三围同值恢复"语义误导) | 消耗品走 `BaseItem.onUse → CombatManager.applyEffect` 按 `effects` 类型分别恢复,`useItem` 从未接线 | 删除该方法,README 方法表与遗留说明同步(装备/消耗品使用入口统一在 `Inventory.useItem`) | > 验证(宿主):真 WebSocket 端到端新增断言——服务器权威 `entity:damaged`(targetUid=本机 `U_N`) → 本地玩家血量经游戏管线权威覆盖(此前只验证服务器广播、未验证客户端应用)。宿主全量断言 + 网络核心 47 项自检全绿。 ### 已完成 ✅ — 装备属性加成 attackBonus/defenseBonus(2026-09-03) 武器/防具的 `attackBonus`/`defenseBonus` 此前只挂在模板与物品实例上、从未进入伤害计算;本次打通 装备 → 属性 → 战斗 闭环: | 改动 | 说明 | |------|------| | `Inventory.equipItem(slotIndex, user)` 真正接线 | 物品实例推入 `user.equipmentItems`(注册表优先、模板兜底创建),触发 `BaseItem.onEquip`(`ITEM_EQUIPPED` 事件);仅 WEAPON/ARMOR 可装备 | | 同类型替换 | 同类型(武器/防具)同时只装备 1 件,装备新件自动卸下旧件(清旧槽 `equipped` 标志 + `onUnequip`) | | `Inventory.unequipItem(slotIndex, user)` | 从 `equipmentItems` 移除并清槽位标志,触发 `ITEM_UNEQUIPPED` | | `useItem` 自动装备 | 武器/防具走 `equipItem` 而非消耗(对齐原设计「消耗品回属性,装备自动装备」);热键/背包使用同一路径 | | `BaseLife.getEquippedByType(type)` | 按类型取当前装备(替换逻辑用) | | `BaseItem.onEquip/onUnequip` 改 public | 供 Inventory 跨组件调用(与 onUse/onPickup/onDrop 同批约定) | > 效果:装备铁剑(+5)后 `getAttackDamage()` = 基础攻击 + 5;装备皮甲(+3)后 `getDefense()` = 基础防御 + 3;`CombatManager.calculateDamage` 随即反映加成。 > 宿主:背包 UI 双点武器/防具 = 装备/卸下(替换原先「未接通仅示意」);无头测试新增第 10 节(铁剑/皮甲/战斧替换/卸下/带装备战斗扣血)断言。 > 遗留:`ItemEffect` 的 speed/damage/defense 临时 buff(带 `duration`)仍为占位空实现,属 Phase 3 buff 系统,与装备加成正交。 ### 首批 Demo 目标 **核心流程**(脚本层已全部打通 ✅): ``` GameManager 启动 → 初始化 ItemFactory → 生成玩家 → 玩家 WASD 移动 → 发现敌人 → 空格/J 攻击(范围检测找最近敌人) → 伤害计算 → 敌人死亡 → 掉落物品(面包/绷带) → 按 E 拾取 → 加入背包 → 按 I 打开背包 → 使用/装备物品 → 按 Q 丢弃 → 地图生成物品节点 → 耐久度耗尽自动销毁 → 玩家死亡 → 3 秒后自动复活 → 循环 ``` ### 暂不包含(保留扩展点) - [x] 装备属性加成(2026-09-03 已接通:Inventory 装备 → BaseLife.equipmentItems → 伤害计算) - [x] ~~联机功能~~(Phase 4.1 客户端核心已完成;服务器 / demo 见 Phase 4.2 待宿主) - [ ] 精确碰撞检测(用 CC 自带碰撞组件,脚本层只处理逻辑) - [ ] 地图生成(SimpleMap 作为参考,具体游戏各自实现) ### 待优化方向(提醒,后续展开讨论)📌 针对 `WorldManager.ts` 的进阶优化,按优先级排列: - [ ] **空间索引**(四叉树/空间网格)— 优化 `getEntitiesInRange` 的 O(n) 遍历,>200 实体时性能瓶颈 - [ ] **对象池** — 掉落物/实体频繁 `new Node()` + `destroy()` 造成 GC 抖动,复用节点 - [ ] **实体类型过滤** — 按类型/标签查询,不只 `getLivesInRange` 一种 - [ ] **距离排序** — 范围查询返回结果按距离排序(最近优先) - [ ] **序列化/存档** — 世界状态(实体位置/状态)导出 JSON,可恢复 - [ ] **延迟生成/销毁** — 出生动画、淡入、延迟生成效果 - [ ] **掉落表** — 按概率随机掉落,而非调用方硬编码掉落 #### EnemyAI.ts(2026-08-24:已修 bug + 扩展钩子 + 受伤仇恨 ✅,以下为后续可选优化) - [ ] **脱战返回出生点(leash)** — 追丢后走回 `_patrolCenter`,而非原地巡逻 - [ ] **完整阵营系统** — 已初步修复"敌我互锁"(`findNearestPlayer`/仇恨只索敌 `isPlayer`,2026-09-02);多队伍/友方/NPC 阵营仍需设计 - [ ] **远程/范围/AoE 攻击** — 攻击写死近战单体,子类 override `tickAttack` - [ ] **新状态扩展** — 击晕/击退/召唤等,override `tickState` + `onEnterState`/`onExitState` - [ ] **waypoint 巡逻路线** — 替代当前圆形巡逻 - [ ] **寻路/避障** — 目前直线冲,复杂地图需寻路 - [ ] **FSM 抽成通用状态机** — 多敌人类型共用时再抽取 - [ ] **参数数据化** — Inspector 硬编码 → 配置表/JSON #### PlayerController.ts(2026-09-02:已修递归攻击 + 帧同步命中 + 冲刺/冷却/输入锁 ✅,以下为后续可选优化) - [ ] **输入源抽象(高)** — 抽 `IInputSource`(方向 + 动作意图),键盘为第一实现,后续接手柄/虚拟摇杆/网络输入 - [ ] **命中判定回收到 CombatManager(高)** — 目前判定逻辑散在 PlayerController,README 原约定归 CombatManager - [ ] **玩家状态机(中)** — idle/walk/attack/dead,支撑连招/受击硬直/翻滚无敌帧,可借鉴 EnemyAI FSM - [ ] **输入上下文栈(中)** — 背包/暂停/合成/对话多面板互踩,统一"谁接管输入" - [ ] **攻击模型扩展(低)** — 朝向过滤(**已确认设计:当前近战为 360° 命中最近目标**,`findNearestTarget` 纯距离选目标、无朝向扇形点积;如需"面前扇形"的有朝向近战,在具体游戏/叶子子类 override `findNearestTarget` 加 facing 点积即可,基座不改默认)、命中帧可配置、远程/AoE/弹道变体(override `findNearestTarget`/`resolveAttackHit`) #### GameManager.ts(2026-09-02:已修 onDestroy 事件移除失效 + 可破坏物体双重掉落 ✅,以下为后续可选优化) - [ ] **职责边界(高)** — 只做启动+调度;攻击已下沉 PlayerController,掉落表/复活/拾取进一步外置 - [ ] **掉落表配置驱动(高)** — 敌人掉落表硬编码在 `handleEntityDeath`,统一为实体 `dropTable`(对齐 BaseDestructible) - [ ] **物品效果接入(高)** — `ItemEffect` 的 speed/damage/defense 临时 buff 空实现(带 `duration` 的 buff 系统);装备属性加成已接通(2026-09-03) - [ ] **玩家死亡/复活(中)** — 3 秒原地满状态复活过于玩具,缺死亡界面/背包掉落/结算 - [ ] **存档接入(中)** — `Inventory.saveInventory/loadInventory` 已写但无人调用 - [ ] **可破坏物体注册清理(中)** — `BaseDestructible` 死亡后未 `unregisterEntity`,注册表残留 - [ ] **碰撞(低)** — 拾取/索敌是半径距离查询,可接 CC 碰撞组件 - [x] **联机(Phase 4.1 已完成)** — `NetworkSync` 客户端核心 + EventBus 桥;服务器 / demo 待宿主(Phase 4.2) --- ## 讨论顺序(已全部完成 ✅) 以下按依赖顺序排列,已在 2026-08-06 会话中全部实现: 1. ✅ **GameManager(启动脚本)** — 初始化 ItemFactory、生成玩家和敌人、串联各系统 2. ✅ **玩家攻击 → 找目标打伤害** — GameManager + WorldManager 范围检测 3. ✅ **敌人自动索敌** — EnemyAI 通过 WorldManager 自动查找玩家 4. ✅ **E 键拾取** — 检测附近物品 → 加入背包 5. ✅ **Q 键丢弃** — 背包移除 → 地图生成物品节点 6. ✅ **死亡掉落** — 实体死亡 → 地图生成掉落物 7. ✅ **整体联调** — 事件流已打通,GameManager 协调所有模块 --- ## 从旧代码继承的功能 本架构参考了 `archived-old_branch` 分支中已验证的旧代码: | 旧代码文件 | 继承到新架构 | 改进点 | |-----------|------------|--------| | `player/PlayerStats.ts` | `BaseLife.ts` | 合并三围 + 移动 + 战斗 | | `player/PlayerAnimation.ts` | `BaseAnimation.ts` | 帧数可配置,支持一次性动画 | | `enemies/ZombieAI.ts` | `EnemyAI.ts` | 状态机保留,集成到 BaseLife | | `enemies/ZombieController.ts` | `BaseLife.ts` | 合并到 BaseLife,不再分离 | | `items/ItemData.ts` | `ItemFactory.ts` | 物品模板 + 效果系统 | | `items/ItemManager.ts` | `Inventory.ts` | 背包 + 热键栏 + 装备栏 | | `items/ChestController.ts` | `BaseDestructible.ts` | 可破坏物体 + 掉落 | | `core/GameManager.ts` | `WorldManager.ts` | 实体管理 + 单例模式 | | `core/GameManager.ts` | `GameManager.ts` | 启动脚本,串联所有系统 | | `ui/HUDController.ts` | — | 参考(UI 层在 CC 中实现) | | `ui/InventoryUI.ts` | — | 参考(UI 层在 CC 中实现) | | `map/SimpleMap.ts` | — | 参考(地图生成在 CC 中实现) | --- ## 如何扩展(创建新游戏) **总原则:先配置,后叶子子类,最后才考虑改基类 / 新系统**(对齐 §开发策略,主干冻结)。每步改动都应先在宿主可视化试玩 + 无头测试验证。 | 想做什么 | 做法 | 层级 | |---------|------|------| | 新增物品 / 调数值 | `ItemFactory` 加模板;敌人掉落表 / `Harvestable` 掉落表 / 开局物品表加条目 | L0 配置 | | 新增内容条目(物品/武器/Boss/任务/成就/称号/技能/城池/NPC 对话/商城商品…) | 写 `content/<分类>/.json` 配置 + 按命名约定放图(§内容配置化) | 配置层 | | 新采集物 / 建筑 | 新建叶子类继承 `BaseDestructible`,重写 `onHarvest` / `onStageChanged` / 掉落表 | L1 叶子子类 | | 新敌人类型 | 继承 `BaseLife`,配置 `EnemyAI` 参数(或重写钩子 / `tickAttack`) | L1 叶子子类 | | 新玩法系统(合成 / buff / 建造 / 地图生成) | 在 `extensions//` 新建自包含插件,只依赖基座、不改基座,自带宿主验证 | L3 系统插件 | | 联机 / 服务器 | 客户端按 §Network 协议实现;服务器归宿主(Phase 4.2) | 宿主 | | 编辑器侧 | 在 CC 编辑器中拖拽绑定资源和 Prefab,`@property` 调参 | — | | 发布内容(对外身份) | 填 `release/`:`game-info.md`(暂定名 / 玩法 / 操作 / 特性 / 企划)、`confidentiality.md`(保密规则)、`itch-page.md`(平台页终稿);**发布由宿主执行并保密清洗** | 文档(`release/`) | > 引擎 / 语言 / 平台不变(§技术栈);基类接口与事件契约视为冻结,改动需按 §开发策略 Review 门槛评审。 ### 发布内容(release/)— 内容在工厂、发布在宿主 **分工**:每款游戏对外的身份(名字、卖点、玩法介绍、未来企划)与保密提示(敏感词表、检查清单)写在本仓库 `release/`(**随工厂分发、保证 factory 通用**——内容跟游戏走,宿主不感知具体身份);**发布执行(清洗、 组装平台页、上传)由宿主完成**(`cc383script2d-host` 的 `npm run build:release` + `npm run publish`)。 **保密铁律**:对外发布的任何内容只允许出现**玩法与未来企划**,不得出现项目代号 / 仓库地址 / 技术栈 / 内部工程名词;逐词清单与检查清单见 `release/confidentiality.md`,发布脚本按它自动拦截。详见 `release/README.md`。 --- ## 玩法丰富方向(插件化候选) 以下方向均以 `extensions//` 插件形式推进(§开发策略 L3),**不改基座**;标注其复用的基座接口 / 已有基础,供评估插件边界与工作量。 | 方向 | 玩法内容 | 复用的基座接口 / 已有基础 | |------|---------|--------------------------| | 合成系统 | 材料组合 → 装备 / 消耗品 / 建筑 | `ItemFactory` 模板 + 配方表(纯数据);合成台 = `BaseDestructible` 子类 | | 建造 / 家园 | 用材料放置墙 / 工作台 / 篝火,网格放置 + 采集回收 | `Building`(BaseDestructible 子类,继承关系图已预留);`ItemState.PLACED` | | 状态效果 / Buff | `ItemEffect` 的 speed/damage/defense 占位 → 时长 buff / 中毒 / 燃烧 / 减速 | `BaseLife` 钩子 + EventBus(自定义事件名,不动核心契约) | | 敌人 / 战斗深化 | 更多敌人类型、Boss、波次进攻 | `EnemyAI` 子类 override `tickAttack` / `tickState`;`tier` 已示范 normal/elite | | 种植 / 养殖 | 播种 → 生长 → 收获 | `Harvestable` 模式复用(生长阶段 ≈ 渐进破坏阶段表现) | | 钓鱼 | `fishing_spot` 扩展为小游戏 / 概率产出 | `Harvestable`(fishing_spot 已有) | | 地图生成 | 区块 / 资源分布 / 出生点 | `SimpleMap` 参考;读取 `ItemFactory` 与掉落表 | | 天气 / 昼夜 | 影响视野 / 敌人强度 / 产出 | EventBus 广播 + 表现层 | | NPC / 交易 / 商店 | 交互 → 交易面板 | `PlayerController` 交互钩子 + `Inventory` 接口 | | 任务 / 成就 / 引导 | 监听事件计数,发放奖励 | `GameEvents` + `Inventory.addItem` | | 存档 / 读档 | 世界快照 JSON + 背包 | `Inventory.saveInventory/loadInventory`(已写未接) | | 远程 / 技能 / 弹幕 | 远程攻击、技能释放 | `PlayerController` 已预留 override `findNearestTarget` / `resolveAttackHit`;`CombatManager` 扩展 | | 烹饪 | 食物组合 → 高级消耗品 | `ItemFactory` 模板 + `ItemEffect` | | 装备强化 / 附魔 | 消耗材料升级装备数值 | `attackBonus/defenseBonus` 已接入;模板扩展 | | 经验 / 升级 | 击杀得经验、加点 | `ENTITY_DIED` + `BaseLife` 属性 | | 仓库 / 箱子 | 分类、扩容、存储 | 箱子 = `BaseDestructible` 子类;`Inventory` 扩展 | ### 玩法蓝图评估(2026-09-04)— 28 项 + 发散 > 承接上方 16 项候选(部分重叠:任务 / 存档 / 建造 / 技能等在此细化拆分)。列:**成本**(低/中/高)|**复用 / 依赖**|**阶段**(早/中/远,相对现有闭环)|**发散**(同一主题、用户未列但同属的衍生想法)。§内容配置化 成立后,多数系统的「条目内容」都是配置,本表只评估**系统机制**。 **A. 局外与长线(Meta / 运营层)** | # | 想法 | 成本 | 复用 / 依赖 | 阶段 | 发散 | |---|------|------|------------|------|------| | 1 | 局外成长 / 局外物品 / 局外页面 | 中 | 存档(saving) + 局外 UI;roguelike 式「每局结算 → 回填局外进度」 | 远 | 图鉴 / 收集系统、段位 / 头衔、首通奖励、赛季结算回放 | | 13 | 日常系统(签到 / 活跃度 / 月卡 / 季票) | 中 | 存档 + 定时器 + 商城;每日 / 每周重置 | 远 | 连续签到奖励、活跃宝箱、通行证路径、限时活动 | | 14 | 全局成就系统 | 低-中 | `GameEvents` 计数 + 存档 + 称号 | 中 | 隐藏成就、成就点数兑换、进度分阶徽章、成就称号 | **B. 任务与内容** | 2 | 任务系统 | 中 | `GameEvents` + NPC 对话 + 存档;目标类型化(击杀 / 采集 / 到达 / 合成 / 交付) | 中 | 任务链 / 剧情任务、日常周常、隐藏 / 分支 / 多结局、对话配置化 | **C. 战斗深化** | 3 | Boss 多阶段 + 大血条 UI | 中 | `EnemyAI` 子类 + 多阶段状态机(锁血转阶段)+ 顶部大血条 UI | 早 | Boss 专属材料 → 独有装备、Boss 词缀变体(腐化 / 精英化)、世界 Boss | | 10 | 角色天赋与技能系统 | 高 | 新技能资源(蓝 / 怒 / 冷却)+ 技能树配置 + 主动 / 被动 | 中 | 双天赋切换、天赋重置道具、技能升级 | | 11 | 装备 / 道具概率招募(gacha) | 中 | 概率池配置 + 保底 + 稀有度 / 词缀联动 | 中 | 十连、限定池、心愿单、招募表现 | | 18 | PvP 竞技场 | 高 | 联机 + 匹配 + 观战 / 录像 + 段位;依赖战斗区(#24) | 远 | 竞技场赛季、段位保护、禁词缀平衡 | **D. 社交与公会** | 4 | 社交 / 关系绑定 / 赠礼 | 中 | 联机 + 好友数据 + 亲密度 + 邮件 | 中 | 师徒 / 结义 / 伴侣关系、出师奖励、仇人 / 复仇标记 | | 5 | 多类商城、商店、交易系统 | 中 | `Inventory` + 商店 UI + 货币 + 邮件 | 中 | 玩家摆摊、拍卖行 / 交易所、声望 / 限定兑换、限时轮换 | | 16 | 公会系统 | 高 | 联机 + 公会大厅 / 仓库 / 任务 + 公会战 | 远 | 公会等级 / 科技 / 排行、领地争夺(与 #15 联动) | **E. 世界与领土** | 8 | 野外 / 主城 / 执法队 / 处罚与监狱 | 高 | 区域标记 + 安全区(#24)+ PK / 红名惩罚状态 | 中 | 治安值、通缉榜、红名爆装、监狱时长惩罚 | | 15 | 中立可攻占城池 / 据点 + 领主军队 | 高 | 区域归属 + 征收 / 税收 + 兵种招募培养;英雄 / 将军 = 玩家 | 远 | 定时攻城战、城池升级 / 防御工事、兵种克制、税收再投资 | | 17 | 小地图 / 大地图 / 传送 | 中 | 区块 + 传送点 UI + 区域解锁条件 | 中 | 驿站 / 锚点、传送费用、探索迷雾 | | 24 | 战斗区 / 非战斗区 | 低 | 区域标记 + 技能 / 攻击类道具封锁 | 早 | 安全区保护倒计时、红名禁入主城 | | 6 / 27 | 家园系统;领地家园可编辑(建筑 / 家居) | 中 | `Building` + 网格放置 + 蓝图 | 早 / 中 | 家具交互、防御塔 / 入侵事件、蓝图保存 / 分享 | **F. 生产与经济** | 19 | 食品保质期 | 低 | 物品时间戳 + 腐败状态 + 加工 | 早 | 冷藏 / 腌制延长、过期毒害、新鲜度品质 | | 20 | 挂机系统(钓鱼 / 悟道场 / 采矿…) | 中 | 定时结算 + 低概率产出表 + 场景 | 中 | 离线收益、挂机位置加成、托管队列 | | 25 | 更丰富的食品与制作方法 | 低-中 | `ItemFactory` + 配方表 + 烹饪 | 早 | 配方树、厨师升级、食材品质影响 | | 26 | 武器锻造 / 合成 / 精炼 / 强化 / 附魔 / 前后词缀 / 镶嵌 / 词条 / 升阶 | 高 | `ItemFactory` + 词缀库 + 镶嵌孔 + 强化等级 + 升阶;与 11 / 词缀联动 | 中 | 锻造熟练度、失败保底 / 降级、材料品质影响 | **G. 生物 / 伙伴 / 形态** | 12 | 宠物培育 / 稀有度 / 寿命 | 中 | `BaseLife` + 培育(喂食 / 成长 / 进化)+ 寿命计时 + 稀有度 | 中 | 宠物技能 / 装备、进化分支、寿命延长道具 | | 21 | 疾病系统 | 中 | buff / 状态异常 + 传染 + 治疗 / 药方 | 中 | 抗性、季节性疾病、疫苗 | | 22 | 巨型驾驭(巨兽 / 机甲 / 法天相地) | 高 | 大体型形态替换个体攻击 + 独立技能条;区别于坐骑 | 远 | 形态升级、合体技能、能量条 | **H. 表现与其它模式** | 9 | 装备栏页面 / 载具作装备 / 装备贴图动画目录 | 中 | 多部位槽位 + 载具作为装备槽 + 资产目录结构约定(§内容配置化) | 早 | 多部位(头 / 身 / 手 / 脚 / 饰品)、染色 / 幻化 / 皮肤 | | 23 | 过场动画系统 | 中 | 特殊道具 / 技能触发 + 可跳过 + 回放 | 中 | 剧情选择分支、CG 目录约定 | | 28 | 嵌入其它游戏模式(3D 过肩副本 / 第一人称巢穴 / moban 等) | 高 | 模式管理 + 视角切换 + 沙盒隔离 | 远 | 模式入口管理、跨模式数据隔离 | > **优先级建议(2026-09-04 更新)**:内容配置化 → 插件隔离契约 → 词缀 loot → 战斗区 / 安全区 + Boss → 食品 / 保质期 / 制作 → 任务 / 成就 → 家园 / 城池 → 社交 / 商城 / 日常 → 联机类(PvP / 公会 / 副本)→ 巨型驾驭 / 模式嵌入。 > 原有短期建议(保留):合成 → 建造 → 存档 → Buff —— 靠近已有基础、改动小、见效快;每个插件完成即固化宿主回归断言(L2 验收入口)。 > 进度:**合成 / 存档 / Buff 已落地**(2026-09-03,见 extensions/README);**建造**(网格放置 + `Building`,体量大)为下一候选。 --- ## 开发路线图 > **开发方式注记**:主干已冻结(§开发策略)。Phase 2~4 未完成项一律在 feature 分支 / 独立仓库推进;玩法优先走 L0 配置 / L1 叶子子类,宿主为验收入口。 ### Phase 1 — 核心架构 ✅ 已完成 - [x] 基础类结构设计 - [x] Core 层:BaseEntity / BaseAnimation / EventBus / CameraController / GameManager - [x] Life 层:BaseLife / PlayerController / EnemyAI - [x] Item 层:BaseItem / Inventory / ItemFactory - [x] World 层:BaseDestructible / WorldManager - [x] Combat 层:CombatManager - [x] Network 层:NetworkSync(预留接口) - [x] **Demo 逻辑完善** — GameManager 串联各系统,攻击/索敌/拾取/丢弃/死亡掉落全流程打通 ### Phase 2 — Demo 验证(逻辑已验,CC 集成待启动) - [x] **Demo 逻辑验证**(宿主先行,2026-09-03):生成/移动/战斗/掉落/拾取/背包/采集/装备全流程 109 项断言全绿 - [ ] 导入 CC 编辑器,创建场景,跑通完整 Demo(作者回归后) - [ ] 修复集成问题 ### Phase 3 — 功能完善 - [x] 装备属性加成系统(2026-09-03:attackBonus/defenseBonus 已生效) - [ ] 合成系统 - [ ] 更多敌人类型 - [ ] 建筑系统完善 ### Phase 4 — 联机 - [x] **联机架构设计确定** — 差异约束 + 分层(纯核心 / WebSocket 传输 / 服务器归宿主);v1 采用客户端权威-lite,后续转服务器权威 - [x] **NetworkSync 客户端核心(Phase 4.1)** — 协议 / 序列化 / 传输 / 出入站映射 / 幽灵同步 / EventBus 桥,纯核心 47 项自检全绿 - [x] **服务器 + 双窗口联机 demo(Phase 4.2,服务器侧由宿主实现,2026-09-03)** — WebSocket 中继(JOIN/中继/转发)+ 双窗口/跨机联机验证 + 无头测试 - [x] **服务器权威共享敌人(Phase 4.3,服务器侧由宿主实现,2026-09-03)** — 服务器模拟/权威血量/死亡/掉落全服一致 + 敌人攻击玩家 - [ ] **多玩家测试与优化** — 平滑插值、断线重连、服务器权威化进一步推进(共享实体分叉修复) --- ## 技术栈 - **引擎**:Cocos Creator 3.8.3 - **语言**:TypeScript - **平台目标**:待定(小程序 / 局域网 / 跨平台)