first commmit

This commit is contained in:
jakciehan
2026-05-06 08:17:32 +08:00
commit 427a33c55b
269 changed files with 20906 additions and 0 deletions
@@ -0,0 +1,369 @@
# 《影之传说:忍者救公主》开发需求文档
## 引言
本文档基于 `doc/影之传说_详细策划案.md` v2.0 版本提炼,用于指导微信小游戏《影之传说:忍者救公主》MVP 版本的研发工作。产品定位为横版动作闯关类微信小游戏,核心体验包含:悬浮式双手操作、抛物线跳跃+物理跳跃限制、双攻击按钮互斥、水晶玉自动升级、蝴蝶显形 BOSS 战、3 章 15 关循环制关卡与怀旧像素美术风格。
本需求文档聚焦于**可落地的软件功能需求**,按照子系统进行分组,并以 EARSEasy Approach to Requirements Syntax)语法描述每一条验收标准。实际实现计划将在后续任务清单(task-item.md)中进一步拆解。
### 技术栈约束
- 游戏引擎:Cocos Creator 3.8.x
- 开发语言:TypeScript
- 运行平台:微信小游戏(基础库 2.16.0+)
- 屏幕方向:**横屏(Landscape)**,强制锁定横向显示,禁止玩家旋转竖屏
- 设计分辨率:960×540(16:9 横屏基准),按设备宽高比自适应缩放,支持常见比例(16:9 / 18:9 / 19.5:9 / 20:9
- 首包 ≤ 4MB,锁帧 30fps
- 美术参考资源:`images/影.png``images/敌人.png``images/场景.png`
### 范围界定(已确认)
- **本期范围(MVP,仅第一章)**:
- 第一章 5 关(1-1 初始森林 → 1-5 魔城天守阁 BOSS 战)
- 核心战斗系统(移动/跳跃/攻击/格挡/自动升级)
- 悬浮操作 UI 系统(摇杆 + 跳跃 + 双攻击按钮)
- 蝴蝶显形 BOSS 战(双幻坊)
- 基础 UI 流程(主菜单 / 关卡选择 / 设置 / 结算)
- 剧情背景介绍(正式进入关卡前的背景过场)
- 新手引导(前 3 关)
- 本地存储与音效音乐
- **明确不在 MVP 范围**
- 第二章(红叶之章)、第三章(雪之章)
- 商业化模块(激励视频、插屏、Banner、内购商品、月卡、钻石体系)
- 社交功能(微信排行榜、分享、好友助力、公会)
- 成就与皮肤系统
- 轻度(普通)难度模式——已完全移除
- 第二/三章相关的赛季、节日活动
---
## 需求
### 需求 1:悬浮操作 UI 系统
**用户故事:** 作为一名移动端玩家,我希望拥有一套参考《王者荣耀》风格的悬浮按钮操作系统(虚拟摇杆 + 跳跃 + 双攻击按钮),以便在游戏画面不被遮挡的前提下完成移动、跳跃、攻击的精确操作。
#### 验收标准
1. WHEN 游戏进入关卡 THEN 系统 SHALL 在独立 UI 图层按**横屏布局**渲染虚拟摇杆(左下,直径 120px)、跳跃按钮(摇杆右上方,直径 90px)、手里剑攻击按钮(右下偏左,直径 90px)、忍者刀攻击按钮(右下偏右,直径 90px),默认透明度 70%,并保证左右两组按钮分别位于屏幕左右 1/3 安全区内,不遮挡战斗视野。
2. WHEN 玩家手指按下任一悬浮按钮 THEN 系统 SHALL 在 30ms 内给出视觉反馈(按钮缩放 10% 或变为 100% 不透明)。
3. WHEN 玩家的触控点位于按钮区域外 THEN 系统 SHALL 将该触控事件穿透至游戏场景层处理。
4. WHEN 玩家在摇杆可见范围之外按下屏幕 THEN 系统 SHALL 计算从摇杆中心到该点的方向向量,作为角色移动方向输入。
5. IF 触控点位于摇杆中心 10px 死区内 THEN 系统 SHALL 视为无方向输入。
6. WHEN 玩家长按并拖动任一悬浮按钮进入"布局设置模式" THEN 系统 SHALL 允许调整按钮位置、大小、透明度,并将设置持久化到本地存储。
7. WHEN 设备屏幕尺寸或宽高比变化(常见 16:9 / 18:9 / 19.5:9 / 20:9 横屏)THEN 系统 SHALL 自动按安全区域重新排布悬浮按钮,避免被刘海、听筒凹槽或 Home Indicator 遮挡。
8. WHEN 多个悬浮按钮同时被按下 THEN 系统 SHALL 支持至少 3 点以上的同时触控,不得出现任何一个按钮被丢弃事件。
---
### 需求 2:角色移动与跳跃物理系统
**用户故事:** 作为一名玩家,我希望角色的移动和跳跃具备真实的物理感(支持抛物线轨迹、禁止空中二段跳),以便获得有策略感的闯关体验。
#### 验收标准
1. WHEN 玩家推动摇杆至左/右方向 THEN 角色 SHALL 按对应方向以 100px/秒(红衣/绿衣)或 150px/秒(黄衣)持续移动。
2. WHEN 玩家单击跳跃按钮且角色处于地面或有支撑物的状态 THEN 角色 SHALL 触发标准垂直跳跃(高度 250px,黄衣 300px)。
3. WHEN 玩家长按跳跃按钮 ≥ 0.5 秒并释放 THEN 角色 SHALL 触发蓄力高跳(高度 375px)。
4. IF 角色当前处于空中(无地面/支撑物)THEN 系统 SHALL 禁用跳跃按钮响应,并将按钮视觉置为半透明。
5. WHEN 玩家将摇杆保持在 45°(右上)或 135°(左上)方向的同时按下跳跃按钮 THEN 角色 SHALL 按抛物线轨迹(`↗``↖`)跳跃,而非垂直跳跃。
6. WHEN 玩家保持摇杆在 45°/135° 区域 THEN 系统 SHALL 在按下跳跃前显示抛物线轨迹预览光效。
7. WHEN 角色处于跳跃过程中(硬核模式)THEN 系统 SHALL 不允许通过摇杆横向改变空中轨迹(还原原作"起跳定型")。
8. WHEN 角色起跳 THEN 系统 SHALL 在真正离地前插入约 150ms 的下蹲延迟动画。
---
### 需求 3:攻击系统(双按钮互斥 + 攻防一体)
**用户故事:** 作为一名玩家,我希望通过两个独立且互斥的攻击按钮分别控制手里剑和忍者刀,以免去武器切换操作,并保留忍者刀"攻防一体"的格挡特性。
#### 验收标准
1. WHEN 玩家点击手里剑攻击按钮 THEN 系统 SHALL 激活手里剑武器并将忍者刀按钮置为未激活状态(半透明)。
2. WHEN 玩家点击忍者刀攻击按钮 THEN 系统 SHALL 激活忍者刀武器并将手里剑按钮置为未激活状态(半透明)。
3. IF 两个攻击按钮被同时按下 THEN 系统 SHALL 仅以最先按下的按钮为准,忽略另一输入。
4. WHEN 手里剑按钮激活并被点击 THEN 系统 SHALL 按当前手里剑等级的攻击速度(标准 0.3 秒/发,升级 0.25 秒/发)向角色朝向发射手里剑。
5. WHEN 玩家长按手里剑按钮 THEN 系统 SHALL 触发最多 3 连发的连射模式。
6. WHEN 忍者刀按钮激活并被点击 THEN 系统 SHALL 以 0.5 秒/次的攻击间隔进行近战挥砍。
7. WHEN 角色处于"忍者刀攻击中"的判定帧内 AND 敌人攻击类型为"shuriken"或"sword"THEN 系统 SHALL 判定为成功格挡,角色不受伤并触发格挡特效与音效。
8. WHEN 角色处于"忍者刀攻击中"的判定帧内 AND 敌人攻击类型为"fireball"或"smoke_bomb"THEN 系统 SHALL 不触发格挡,按正常受伤流程处理。
9. WHEN 攻击按钮处于冷却期 THEN 按钮 SHALL 显示半透明状态以示冷却。
---
### 需求 4:组合操作(移动+跳跃+攻击三合一)
**用户故事:** 作为一名玩家,我希望可以同时进行移动、跳跃与攻击,以便在空中灵活应对敌人。
#### 验收标准
1. WHEN 玩家同时按下跳跃按钮和攻击按钮(100ms 内)THEN 系统 SHALL 识别为跳跃攻击组合,角色在跳跃过程中执行攻击动作。
2. WHEN 玩家在抛物线跳跃(45°/135°)过程中按下攻击按钮 THEN 系统 SHALL 允许角色在抛物线轨迹中发射手里剑或近战挥砍。
3. WHEN 玩家同时操作摇杆(任意方向)+ 跳跃按钮 + 攻击按钮 THEN 系统 SHALL 同时响应三种输入,角色表现为"边移动边跳跃边攻击"。
4. WHEN 组合操作触发 THEN 系统 SHALL 叠加显示相应的组合光效(跳跃光效 + 攻击光效)。
5. WHEN 防误触判定启用 THEN 系统 SHALL 结合触控时间、触控区域与压力信息,组合识别准确率 ≥ 95%。
---
### 需求 5:角色状态与自动升级系统
**用户故事:** 作为一名玩家,我希望通过拾取水晶玉让角色自动变身为绿衣/黄衣并自动升级手里剑,以便获得正向成长反馈且无需手动操作。
#### 验收标准
1. WHEN 角色处于红衣状态且拾取 1 个水晶玉 THEN 角色 SHALL 立即切换为绿衣状态,手里剑自动升级为"升级手里剑"(攻击力 2、体积增大)。
2. WHEN 角色处于绿衣状态且拾取第 2 个水晶玉 THEN 角色 SHALL 立即切换为黄衣状态,手里剑进一步强化(攻击速度 0.25 秒/发),移动速度提升到 150px/秒。
3. WHEN 角色处于绿衣/黄衣状态且被普通攻击(刀斩/手里剑/十字镖)命中 THEN 角色 SHALL 立即回退到红衣状态,所有强化效果清零,但不立即死亡(相当于消耗一次保险)。
4. WHEN 角色处于红衣状态且被任意攻击命中 THEN 角色 SHALL 立即死亡。
5. IF 角色处于任意状态且被烟玉或火球命中 THEN 角色 SHALL 立即死亡,不触发状态回退。
6. WHEN 角色状态切换 THEN 系统 SHALL 播放对应的换装动画与音效,并更新角色贴图(红/绿/黄忍者服,参考 `images/影.png`)。
---
### 需求 6:敌人 AI 与行为系统
**用户故事:** 作为一名玩家,我希望遇到行为差异鲜明的敌人(青忍、赤忍、黑忍、妖坊),以便获得多样化的战斗挑战。
#### 验收标准
1. WHEN 青忍进入战斗状态 THEN 系统 SHALL 按 2.0 秒/次的攻击间隔,远距离投掷十字镖、近距离挥刀攻击。
2. WHEN 赤忍进入战斗状态 THEN 系统 SHALL 以 120px/秒移动,并按 1.5 秒/次的间隔投掷烟玉(攻击力秒杀、不可格挡)。
3. IF 玩家在赤忍视野内停留不前超过 2 秒 THEN 赤忍 SHALL 主动跳跃到玩家前方实施拦截。
4. WHEN 森林关卡中玩家连续击杀 3 个赤忍 THEN 系统 SHALL 随机掉落 1 个点丸或术丸。
5. WHEN 黑忍在城壁关卡被击败 THEN 系统 SHALL 掉落 1 个卷物(魔笛);该卷物若未被拾取则不再刷新。
6. WHEN 妖坊进入攻击状态 THEN 系统 SHALL 按 3.0 秒/次发射直线火球,火球对玩家为秒杀判定。
7. WHEN 摄像机视野外的敌人存在 THEN 系统 SHALL 暂停其 AI 更新以节约性能,进入视野时恢复。
---
### 需求 7:道具与掉落系统
**用户故事:** 作为一名玩家,我希望通过确定性与随机性并存的道具掉落规则获得养成与搜索的乐趣。
#### 验收标准
1. WHEN 森林关卡中累计击杀敌人数达到第 12 个 THEN 系统 SHALL 在屏幕上方固定位置生成 1 个水晶玉(确定性出现)。
2. WHEN 水晶玉生成后 13~20 秒内玩家未拾取 OR 关卡卷轴已将其移出视野 THEN 系统 SHALL 销毁该水晶玉。
3. WHEN 玩家在森林关卡累计击杀 3 个赤忍 THEN 系统 SHALL 随机(50%)掉落点丸(攻击力 +50%,持续 30 秒)或术丸(移速 +30%,持续 20 秒)。
4. WHEN 玩家拾取卷物(魔笛)THEN 系统 SHALL 立即秒杀当前屏幕内所有敌人并播放魔笛特效。
5. WHEN 玩家在密道关卡拾取增丸 THEN 系统 SHALL 永久增加 1 条命(命数上限需保持)。
6. WHEN 任何道具被拾取 THEN 系统 SHALL 播放拾取音效,并在 UI 上刷新对应状态显示。
---
### 需求 8:关卡与场景系统(MVP:第一章 5 关)
**用户故事:** 作为一名玩家,我希望体验到结构清晰、节奏递进的 5 个关卡(森林/洞穴/城壁/魔城/BOSS 战),以获得完整的章节闯关感。
#### 验收标准
1. WHEN 玩家选择 1-1 初始森林 THEN 系统 SHALL 加载横向卷轴场景,要求打倒 3 个妖坊后通关,时限 75 秒。
2. WHEN 玩家选择 1-2 森林深处 THEN 系统 SHALL 加载横向卷轴场景,击败红妖珠坊后通关,时限 85 秒。
3. WHEN 玩家选择 1-3 洞穴/水路 THEN 系统 SHALL 加载左右卷轴场景,击杀 10 个青忍后通关,时限 100 秒。
4. WHEN 玩家选择 1-4 城壁 THEN 系统 SHALL 加载垂直卷轴场景,角色向上跳跃抵达顶层即通关,时限 95 秒。
5. WHEN 玩家选择 1-5 魔城天守阁 THEN 系统 SHALL 加载室内多层场景,发生与双幻坊 BOSS 的战斗。
6. WHEN 1-5 BOSS 战斗中 THEN 系统 SHALL 播放"公主被青忍带走"的过场动画,而**不得**出现"挥刀斩断绳索解救公主成功"的画面。
7. WHEN 玩家击败 1-5 的双幻坊 BOSS THEN 系统 SHALL 进入第一章章节结算界面(展示总得分、总耗时、无伤次数),并提示"公主被带走,续章待续"的 MVP 结局文案。
8. WHEN 场景滚动 THEN 系统 SHALL 按远景/中景/近景/特效 4 层视差滚动(速度比 1:2:4:4),横屏下可视区域横向拓宽,卷轴速度与关卡长度需按 16:9 基准重新标定,确保在 30fps 下稳定渲染。
9. WHEN 玩家在场景中接触树木/石柱 THEN 系统 SHALL 允许其遮挡敌人远程攻击;草丛可短暂隐藏玩家。
---
### 需求 9:BOSS 战(蝴蝶显形 + 一击必杀)
**用户故事:** 作为一名玩家,我希望 BOSS 战保留"先打蝴蝶、再一击必杀"的原作机制,以获得紧张刺激的决战体验。
#### 验收标准
1. WHEN 进入 BOSS 关卡 THEN 系统 SHALL 生成 1 个围绕 BOSS 的蝴蝶对象,BOSS 本体在蝴蝶未被击中前处于无敌状态。
2. WHEN 玩家攻击命中蝴蝶 THEN 系统 SHALL 播放蝴蝶变色动画并触发 BOSS 显形。
3. WHEN BOSS 处于显形状态且被玩家命中任意 1 次有效攻击 THEN 系统 SHALL 判定 BOSS 死亡并进入通关结算。
4. WHEN BOSS 当前血量每减少 1/3 THEN 系统 SHALL 切换其攻击模式(阶段转换)。
5. IF MVP 阶段范围只覆盖双幻坊 THEN 系统 SHALL 至少实现:双人夹击、火球喷射、分身迷惑三种攻击模式的随机或循环触发。
6. WHEN 玩家被 BOSS 秒杀型攻击(火球)命中 THEN 系统 SHALL 立即触发角色死亡流程。
---
### 需求 10:伤害判定与碰撞系统
**用户故事:** 作为一名程序,我希望有一套清晰、稳定、可扩展的碰撞与伤害判定系统,以支撑所有玩家-敌人-道具-环境交互。
#### 验收标准
1. WHEN 两个碰撞体(玩家/敌人/子弹/道具/陷阱)在同一帧发生相交 THEN 系统 SHALL 触发碰撞回调,并根据类型分发处理。
2. WHEN 玩家进入无敌帧状态(例如被击退后的 0.5 秒内)THEN 系统 SHALL 忽略对玩家的所有伤害判定。
3. WHEN 伤害判定调用触发 THEN 系统 SHALL 按以下优先级判定:无敌帧 → 忍者刀格挡 → 攻击类型与距离 → 执行伤害。
4. WHEN 火球与玩家距离 < 100px 且玩家未处于无敌 THEN 系统 SHALL 对玩家造成致命伤害。
5. WHEN 烟玉与玩家距离 < 80px 且玩家未处于无敌 THEN 系统 SHALL 对玩家造成致命伤害。
6. WHEN 玩家攻击与敌人碰撞体相交 THEN 系统 SHALL 根据敌人生命值扣减,死亡后播放死亡动画并在 0.3 秒后销毁(加入对象池)。
---
### 需求 11:新手引导系统
**用户故事:** 作为一名首次进入游戏的玩家,我希望通过前 3 关的引导快速掌握悬浮操作、组合操作与 BOSS 战机制。
#### 验收标准
1. WHEN 玩家首次进入 1-1 THEN 系统 SHALL 按顺序高亮提示:攻击按钮 → 摇杆 → 跳跃按钮,每一步完成指定动作才解锁下一步。
2. WHEN 玩家首次进入 1-2 THEN 系统 SHALL 引导:抛物线跳跃、双攻击按钮互斥、攻防一体格挡、跳跃攻击组合、自动升级机制。
3. WHEN 玩家首次进入 1-3BOSS 教学 THEN 系统 SHALL 引导:蝴蝶显形、BOSS 攻击模式识别、一击必杀时机。
4. WHEN 引导步骤完成 THEN 系统 SHALL 将完成状态写入本地存储,下次进入该关卡不再重复引导。
5. IF 玩家在设置中点击"重新观看引导" THEN 系统 SHALL 允许重置引导状态。
---
### 需求 12:得分、命数与结算系统
**用户故事:** 作为一名玩家,我希望通过分数、命数与连击奖励获得游戏反馈,以便衡量自己的操作水平。
#### 验收标准
1. WHEN 玩家使用忍者刀击杀敌人 THEN 系统 SHALL 按基础分 × 2.0 计算得分。
2. WHEN 玩家使用手里剑击杀敌人 THEN 系统 SHALL 按基础分 × 1.0 计算得分。
3. WHEN 玩家触发完美格挡反击击杀 THEN 系统 SHALL 按基础分 × 3.0 计算得分。
4. WHEN 玩家连续触发"刃接触"(刀剑互击)≥ 5 次 THEN 系统 SHALL 奖励 1500 分连击奖励并播放特效。
5. WHEN 玩家全程无伤通关关卡 THEN 系统 SHALL 按 3 倍基础分数发放奖励。
6. WHEN 玩家在时限内通关 THEN 系统 SHALL 将剩余时间按比例换算为额外分数。
7. WHEN 玩家命数归零 THEN 系统 SHALL 进入游戏失败界面,提供"重试"或"返回主菜单"选项。
8. WHEN 关卡结算 THEN 系统 SHALL 展示本关得分、总分、连击次数、是否无伤,并提供"下一关"或"返回"按钮。
---
### 需求 13:难度模式(仅硬核模式,完全移除轻度模式)
**用户故事:** 作为一名怀旧玩家,我希望游戏只保留硬核难度,并彻底剔除轻度模式相关的分支配置与代码,以完整还原原作一击即死的紧张感。
#### 验收标准
1. WHEN 游戏启动 THEN 系统 SHALL 仅按硬核模式运行,UI 层**不得**出现任何难度选择入口。
2. WHEN 代码实现任何受难度影响的逻辑(跳跃延迟 / 空中轨迹 / BOSS 攻击频率 / 蝴蝶移动 / 起跳延迟等)THEN 系统 SHALL 使用统一的硬核参数,不保留轻度模式分支或开关。
3. WHEN 角色处于红衣状态受到任意攻击 THEN 系统 SHALL 执行一击即死逻辑。
4. WHEN 角色跳跃过程中 THEN 系统 SHALL 不允许空中调整轨迹(保留原作"起跳定型")。
5. WHEN 起跳事件触发 THEN 系统 SHALL 保留约 150ms 的下蹲延迟。
6. WHEN 配置表加载 THEN 系统 SHALL 只加载硬核难度的关卡/敌人/BOSS 数值数据,不得加载轻度模式配置。
---
### 需求 14:第一章结局叙事(MVP 范围内)
**用户故事:** 作为一名玩家,我希望在第一章 BOSS 战结束时看到"公主被青忍带走"的过场,而非"斩绳救人成功",以强化紧张感并为后续章节埋下叙事钩子。
#### 验收标准
1. WHEN 玩家与 1-5 双幻坊展开战斗 THEN 系统 SHALL 在 BOSS 血量减少至 1/2 时播放"公主被青忍带走离开"的短过场(≤ 3 秒,画面不暂停战斗)。
2. WHEN 玩家击败双幻坊 THEN 系统 SHALL 播放"公主被带走"的定格画面(≤ 2 秒)并无缝衔接至章节结算界面。
3. WHEN 章节结算界面展示完成 THEN 系统 SHALL 提供"回到主菜单"与"重玩第一章"两个选项。
4. WHEN 该过场与结算播放过程中 THEN 系统 SHALL 允许玩家通过点击"跳过"按钮直接进入结算界面。
5. 系统 SHALL **不得** 出现"挥刀斩断绳索解救公主成功"的画面。
---
### 需求 15:美术资源与场景还原
**用户故事:** 作为一名美术,我希望以 `images/影.png``images/敌人.png``images/场景.png` 作为参考,实现风格统一的像素化简化版资源。
#### 验收标准
1. WHEN 渲染主角的红/绿/黄三种形态 THEN 系统 SHALL 参考 `images/影.png` 的配色、体型、面罩、服饰细节,各形态尺寸 16×32px。
2. WHEN 渲染青忍、赤忍、黑忍、妖坊 THEN 系统 SHALL 参考 `images/敌人.png` 的造型与配色,尺寸分别为 16×16、16×16、20×24、18×20。
3. WHEN 渲染双幻坊、雾雪之介、雪草妖四郎 BOSS THEN 系统 SHALL 参考 `images/敌人.png` 的 BOSS 造型,尺寸不低于 32×32。
4. WHEN 渲染森林/城墙/魔城三种场景 THEN 系统 SHALL 参考 `images/场景.png` 实现 4 层视差(远/中/近/特效),每场景独立调色板不超过 48 色(含角色共用 16 色)。
5. WHEN 场景切换章节风格(青叶/红叶/雪原)THEN 系统 SHALL 通过切换调色板与落叶/飘雪粒子特效呈现季节变化,而非重做场景。
---
### 需求 16:音效与音乐系统
**用户故事:** 作为一名玩家,我希望在关键操作(攻击/跳跃/受伤/拾取/格挡)和关卡/BOSS 战中有清晰的音频反馈。
#### 验收标准
1. WHEN 角色执行攻击/跳跃/受伤/拾取道具/成功格挡 THEN 系统 SHALL 播放对应的 WAV 音效(attack/jump/hurt/pickup/parry),时长控制在 0.2~0.5 秒。
2. WHEN 玩家进入森林/城墙/魔城关卡 THEN 系统 SHALL 播放对应的 MP3 背景音乐(bgm_forest/bgm_castle/bgm_final)。
3. WHEN 玩家进入 BOSS 战 THEN 系统 SHALL 切换为 BOSS 战专属 BGMbgm_boss)。
4. WHEN 玩家在设置中调整 BGM/音效音量 THEN 系统 SHALL 即时生效并持久化到本地存储。
5. WHEN 游戏总音频包被打包 THEN 总体积 SHALL ≤ 500KB。
---
### 需求 17:本地存储与设置
**用户故事:** 作为一名玩家,我希望关卡进度、操作布局、音量等设置在下次打开游戏时仍然保留。
#### 验收标准
1. WHEN 玩家通关任一关卡 THEN 系统 SHALL 将解锁状态写入本地存储(wx.setStorageSync)。
2. WHEN 玩家调整悬浮按钮布局/透明度/大小 THEN 系统 SHALL 将其持久化,并在下次启动时还原。
3. WHEN 玩家调整 BGM/音效音量 THEN 系统 SHALL 持久化音量配置。
4. WHEN 玩家完成/跳过新手引导 THEN 系统 SHALL 记录引导完成状态。
5. WHEN 玩家首次观看或跳过剧情背景介绍 THEN 系统 SHALL 记录"背景介绍已观看"状态并在后续启动时默认跳过(需求 19)。
6. IF 本地存储读取失败 THEN 系统 SHALL 使用默认配置启动,不得导致游戏崩溃。
---
### 需求 18:性能与兼容性
**用户故事:** 作为一名玩家,我希望在主流微信用户的设备上都能获得流畅的游戏体验。
#### 验收标准
1. WHEN 游戏运行在高端机(A12+/骁龙 855+THEN 帧率 SHALL ≥ 30fps,全特效开启。
2. WHEN 游戏运行在中端机(骁龙 660+THEN 帧率 SHALL ≥ 30fps,中等特效。
3. WHEN 游戏运行在低端机(入门级)THEN 帧率 SHALL ≥ 25fps,可关闭粒子特效。
4. WHEN 关卡切换 THEN 系统 SHALL 清理未使用资源,内存峰值 ≤ 200MB。
5. WHEN 对象(敌人/子弹/特效)生成与销毁 THEN 系统 SHALL 使用对象池进行复用,避免频繁 GC。
6. WHEN 游戏在 iPhone 刘海屏或异形屏**横屏**运行 THEN 系统 SHALL 自动识别左右两侧安全区域并对 UI 进行黑边或偏移处理,避免摇杆与攻击按钮被刘海/听筒区遮挡。
7. WHEN 游戏包被打包 THEN 首包体积 SHALL ≤ 4MB,其余资源按关卡分包加载。
---
### 需求 19:剧情背景介绍系统(正式进关前的背景交代)
**用户故事:** 作为一名玩家,我希望在正式进入关卡前能看到一段简短的背景交代(主角身份、公主被捕、忍者使命等),以便快速沉浸到忍者故事世界观中。
#### 验收标准
1. WHEN 玩家首次从主菜单点击"开始游戏"或首次进入 1-1 初始森林 THEN 系统 SHALL 先播放一段≤ 30 秒的"第一章背景介绍"过场后再加载关卡场景。
2. WHEN 背景介绍过场播放 THEN 系统 SHALL 采用分页推进的像素插画 + 打字机文案呈现,至少包含 3 页:主角忍者身份介绍、公主被青忍划走的事件、主角启程解救的使命。
3. WHEN 过场每页展示过程中 THEN 系统 SHALL 在屏幕右下角提供**"跳过"** 按钮与屏幕左下角提供"下一页"指示,并支持点击任意区域加速打字动画的显现速度。
4. WHEN 玩家点击"跳过" THEN 系统 SHALL 立即终止过场并加载 1-1 关卡,不得要求二次确认。
5. WHEN 背景介绍过场首次播放完成或被跳过 THEN 系统 SHALL 将完成状态写入本地存储,后续重新进入游戏时**不再自动播放**。
6. IF 玩家在设置界面点击"重新观看背景介绍" OR 选择"重玩第一章" THEN 系统 SHALL 重置该状态并允许再次观看。
7. WHEN 背景介绍过场播放时 THEN 系统 SHALL 播放专属背景音乐(可复用 `bgm_story` ,总音频体积计入 ≤ 500KB 预算),并尊重玩家在设置中的 BGM/音效音量。
8. WHEN 背景介绍过场处于**横屏**展示 THEN 系统 SHALL 按 960×540 基准布局,适配左右安全区,文字不得被刘海 / 听筒 / Home Indicator 遮挡。
9. WHEN 过场结束且进入 1-1 关卡 THEN 系统 SHALL 无缝衔接至新手引导(见需求 12.1),不得引入额外的点击等待。
---
### 需求 20:核心性能埋点指标(来源于玩家体验验证)
**用户故事:** 作为一名 QA/策划,我希望在关键操作路径上埋点,以便量化验证悬浮操作体验是否达标。
#### 验收标准
1. WHEN 玩家按下悬浮按钮 THEN 触控响应延迟 SHALL < 50ms。
2. WHEN 玩家的物理状态(地面/空中)变化 THEN 跳跃按钮视觉状态切换延迟 SHALL < 50ms。
3. WHEN 玩家在 45°/135° 方向进行抛物线跳跃 THEN 角度识别准确率 SHALL ≥ 95%。
4. WHEN 玩家触发跳跃+攻击组合 THEN 系统组合识别延迟 SHALL < 100ms。
5. WHEN 玩家处于空中状态 THEN 跳跃禁用执行率 SHALL ≥ 99%。
6. WHEN 埋点数据收集 THEN 系统 SHALL 支持抛物线跳跃流畅度与跳跃攻击流畅度的评分统计(目标 ≥ 4.2/5.0)。
---
## 非功能需求概述
- **安全性**:本地存储数据做基础校验,防止被简单篡改(如伪造关卡解锁)。
- **可维护性**:代码分层(表现 / 逻辑 / 数据),单文件职责单一;核心逻辑单元测试覆盖率 ≥ 80%。
- **可扩展性**:敌人 / 道具 / 关卡 / BOSS 通过数据驱动(JSON 配置),便于后续扩展第二 / 三章内容,但配置结构须在当前实现中预留扩展位,**不新增**第二 / 三章的真实数据文件。
- **合规性**:美术 / 音频全部原创或取得合法授权,避免 IP 版权风险;游戏名称避开潜在侵权词汇。
- **无网络依赖**:MVP 版本不依赖网络接口,完全离线可玩,避免对微信后台服务的强耦合。
---
## 范围决策记录(Decisions Log
| 序号 | 决策事项 | 结论 |
|------|---------|------|
| D-1 | 商业化模块(广告 / 内购 / 月卡) | **不纳入 MVP**,预留扩展点但不实现 |
| D-2 | 第二章 / 第三章关卡 | **不实现**MVP 仅覆盖第一章 5 关 |
| D-3 | 社交功能(排行榜 / 分享 / 好友助力) | **非必需,不纳入 MVP** |
| D-4 | 轻度(普通)难度模式 | **完全移除**,UI 与代码中不保留任何轻度模式入口或分支 |
@@ -0,0 +1,127 @@
# 实施计划 — 《影之传说:忍者救公主》MVP(仅第一章,横屏)
> 以下任务基于 [requirements.md](./requirements.md) 中的 20 条需求,按"自底向上 + 可独立验证"的顺序组织。每一个子任务均为可执行的编码步骤,可独立提交与测试。
>
> **核心约束**:横屏(Landscape)锁定、设计分辨率 960×540、Cocos Creator 3.8.x + TypeScript、微信小游戏、首包 ≤4MB、锁帧 30fps、仅硬核模式、MVP 仅第一章 5 关。
---
- [ ] 1. 项目脚手架与分层架构搭建
- [ ] 1.1 初始化 Cocos Creator 3.8.x + TypeScript 项目(横屏)
- 创建项目骨架:`assets/scripts/{ui,logic,data,common}``assets/scenes``assets/resources/{prefabs,textures,audio,configs}`
- 配置微信小游戏构建选项(基础库 2.16.0+,锁帧 30fps
- **在 Cocos Project Settings + `game.json` 中强制横屏**`deviceOrientation: landscape`),设计分辨率 960×540Canvas Fit Height 适配策略
- 接入 ESLint + Prettier + tsconfig 严格模式
- _需求:技术栈约束、18.1 ~ 18.7_
- [ ] 1.2 建立核心基础设施模块
- 实现 `EventBus`(全局事件)、`ObjectPool`(对象池)、`TimeMgr`(暂停/恢复)、`StorageMgr`(封装 `wx.setStorageSync` + 读取失败回退)
- 定义 `Logger` 与分级打点接口,预留性能埋点入口
- 为上述模块补充单元测试(Jest),覆盖率 ≥ 80%
- _需求:17.1 ~ 17.6、18.4 ~ 18.5、20.1 ~ 20.6_
- [ ] 2. 数据驱动配置与类型系统
- [ ] 2.1 定义 TS 接口与 JSON 配置表(仅硬核)
- 编写 `IEnemyConfig``IWeaponConfig``IItemConfig``ILevelConfig``IBossConfig``IStorySceneConfig` 等接口
- 输出第一章 5 关 + 4 种敌人 + 1 个 BOSS(双幻坊)+ 5 种道具(水晶玉/点丸/术丸/魔笛/增丸)+ 2 种武器 + 剧情背景 3 页配置的 JSON
- 实现 `ConfigMgr` 异步加载与校验(缺失字段报错),**不加载任何轻度模式配置分支**
- _需求:6.1 ~ 6.7、7.1 ~ 7.6、8.1 ~ 8.5、9.1 ~ 9.6、13.1 ~ 13.6、19.2_
- [ ] 3. 悬浮操作 UI 系统(横屏布局 + 多点触控)
- [ ] 3.1 实现悬浮 UI 图层与虚拟摇杆(横屏基线 960×540)
- 创建独立 UI Canvas(层级高于游戏场景),按横屏布局渲染摇杆(左下 Ø120px)、跳跃键(摇杆右上方 Ø90px)、手里剑(右下偏左 Ø90px)、忍者刀(右下偏右 Ø90px),默认透明度 70%
- 保证左右两组按钮分别落在屏幕**左右 1/3 安全区**,不遮挡战斗视野
- 实现摇杆死区(10px)、区域外点击方向向量识别、45°/135° 抛物线角度识别区与轨迹预览光效
- 支持横屏安全区自适应(16:9 / 18:9 / 19.5:9 / 20:9,识别**左右两侧**刘海/听筒/Home Indicator),≥3 点多点触控、按钮区优先、非按钮区事件穿透
- _需求:1.1 ~ 1.8、2.5 ~ 2.6、18.6、20.1、20.3_
- [ ] 3.2 实现布局自定义与持久化
- 长按进入布局设置模式,允许拖拽按钮位置、调整大小与透明度
- 将布局写入 `StorageMgr`,下次启动自动还原;读取失败使用横屏默认布局
- _需求:1.6、17.2、17.6_
- [ ] 4. 角色移动与物理跳跃系统
- [ ] 4.1 实现地面检测与横向移动
- 基于简化 AABB 碰撞实现地面/空中状态机,暴露 `isGrounded` 属性
- 摇杆左右方向 → 100/150px/秒移动(红衣/绿衣/黄衣分档)
- _需求:2.1、5.1 ~ 5.2_
- [ ] 4.2 实现物理跳跃与抛物线跳跃
- 实现标准垂直跳(250px)、长按蓄力高跳(375px)、黄衣跳跃(300px)
- 摇杆在 45°/135° + 跳跃按下 → 抛物线轨迹跳跃;空中禁用跳跃按钮并半透明反馈
- 起跳前插入 ≈150ms 下蹲延迟;硬核模式下跳跃过程中禁止横向轨迹调整
- _需求:2.2 ~ 2.8、13.3 ~ 13.5、20.2、20.5_
- [ ] 5. 攻击与状态系统(双按钮互斥 + 自动升级)
- [ ] 5.1 实现双攻击按钮互斥与组合操作
- 点击任一攻击按钮激活对应武器(手里剑 0.3/0.25 s,忍者刀 0.5 s),另一按钮半透明未激活;同时按下以最先按下的为准
- 支持长按手里剑 3 连发;跳跃+攻击(100ms 内)识别为跳跃攻击组合;允许"移动+跳跃+攻击"三合一与组合光效叠加
- _需求:3.1 ~ 3.6、3.9、4.1 ~ 4.5、20.4_
- [ ] 5.2 实现忍者刀攻防一体与角色状态机
- 忍者刀判定帧内对 `shuriken/sword` 类型攻击成功格挡(播放特效+音效),对 `fireball/smoke_bomb` 不格挡
- 角色状态机:红衣 ↔ 绿衣 ↔ 黄衣,拾取水晶玉自动升级,被普攻命中立即降回红衣并清零强化;烟玉/火球直接死亡
- _需求:3.7 ~ 3.8、5.1 ~ 5.6、10.2 ~ 10.5_
- [ ] 6. 敌人 AI、道具与碰撞伤害系统
- [ ] 6.1 实现 4 种敌人 AI
- 青忍(远程十字镖 + 近战刀斩,2.0 s 间隔)、赤忍(120px/s + 烟玉 1.5 s + 主动拦截跳跃)
- 黑忍(城壁关卡掉落魔笛卷物,死亡后不再刷新)、妖坊(3.0 s 直线火球,秒杀)
- 摄像机视野外敌人暂停 AI 更新,进入视野恢复;敌人/子弹统一走对象池
- _需求:6.1 ~ 6.7、18.5_
- [ ] 6.2 实现道具掉落与碰撞伤害判定
- 森林 12 击杀计数 → 水晶玉确定性生成,13~20 s 或移出视野后销毁
- 3 赤忍击杀 → 50% 掉落点丸/术丸;魔笛秒杀全屏;增丸 +1 命
- 统一 `DamageSystem`:无敌帧 → 忍者刀格挡 → 攻击类型/距离判定 → 扣血;火球 <100px、烟玉 <80px 致命
- _需求:7.1 ~ 7.6、10.1 ~ 10.6_
- [ ] 7. 关卡、场景与视差滚动系统
- [ ] 7.1 实现 4 层视差场景与关卡框架(按 16:9 横屏基准标定)
- 抽象 `LevelBase`,加载关卡配置 → 摄像机卷轴(横向/左右/垂直)→ 4 层视差滚动(1:2:4:4)
- **按 16:9 横屏可视宽度重新标定卷轴速度与关卡长度**,保证 30fps 稳定渲染
- 场景互动:树木/石柱遮挡子弹、草丛短暂隐身、藤蔓可攀爬、绳索需挥刀斩断
- _需求:8.8 ~ 8.9、15.4 ~ 15.5、18.1 ~ 18.3_
- [ ] 7.2 实现第一章 5 关内容(1-1 ~ 1-5)
- 按配置表完成 1-1 森林(3 妖坊/75s)、1-2 森林深处(红妖珠坊/85s)、1-3 洞穴水路(10 青忍/100s)、1-4 城壁垂直(顶层/95s
- 1-5 魔城天守阁:进入双幻坊 BOSS 战房间;保证时限、通关条件、场景切换稳定
- _需求:8.1 ~ 8.5、14.5_
- [ ] 8. BOSS 战(双幻坊 蝴蝶显形)与第一章结局叙事
- [ ] 8.1 实现蝴蝶显形与一击必杀机制
- BOSS 战关卡生成环绕蝴蝶对象,未命中前 BOSS 无敌;命中蝴蝶 → 变色并触发 BOSS 显形
- 双幻坊 3 种攻击模式(双人夹击 / 火球喷射 / 分身迷惑)按血量 1/3 阶段切换
- 显形后任一有效命中 → BOSS 死亡;玩家被火球命中立即死亡
- _需求:9.1 ~ 9.6、13.4_
- [ ] 8.2 实现"公主被带走"过场与章节结算
- BOSS 血量 ≤ 1/2 时触发 ≤3s "公主被青忍带走"短过场(战斗不暂停)
- 击败双幻坊 → ≤2s 定格画面 → 无缝进入第一章结算界面;全程不得出现"斩断绳索解救成功"画面
- 过场与结算期间支持"跳过"按钮直达结算
- _需求:8.6 ~ 8.7、14.1 ~ 14.5_
- [ ] 9. 基础 UI 流程、剧情背景、新手引导与得分结算
- [ ] 9.1 实现剧情背景介绍系统(正式进关前的背景交代)
- 新建 `StorySceneCtrl`:按配置加载 3 页像素插画 + 打字机文案,分页推进;右下角"跳过"、左下角"下一页"指示
- 点击屏幕任意区域加速打字显现;点击"跳过"立即终止过场并加载 1-1,无二次确认
- 仅**首次**从主菜单点击"开始游戏"或首次进入 1-1 时自动播放;首次完成/跳过后写入 `StorageMgr`,下次启动默认跳过
- 设置界面提供"重新观看背景介绍"入口、结算界面"重玩第一章"按钮触发状态重置
- 播放专属 `bgm_story`,遵循 BGM/音效音量;960×540 横屏布局下文字避开左右安全区
- 过场结束无缝衔接新手引导(需求 11.1),不引入额外点击等待
- _需求:19.1 ~ 19.9、17.5_
- [ ] 9.2 实现主流程 UI 场景(横屏布局)
- 主菜单(开始游戏/设置/关卡选择)→ 关卡选择(依据本地解锁状态)→ 游戏内 HUD(命数/得分/计时)→ 结算界面(本关得分/总分/连击/无伤)→ 失败界面(重试/返回)
- 设置界面:BGM/音效音量、悬浮按钮布局重置、重置新手引导、**重新观看背景介绍**;**不得出现任何难度选择入口**
- 所有场景均按 960×540 设计,横屏下对刘海/听筒区进行黑边或偏移处理
- _需求:12.7 ~ 12.8、13.1、17.1 ~ 17.6、18.6_
- [ ] 9.3 实现新手引导与得分系统
- 1-1 高亮引导:攻击按钮 → 摇杆 → 跳跃按钮;1-2 引导:抛物线跳跃/互斥按钮/格挡/跳跃攻击/自动升级;1-3 引导:蝴蝶显形/BOSS 攻击识别/一击必杀
- 引导完成状态持久化;得分规则:忍者刀 ×2、手里剑 ×1、完美格挡 ×3、5 连刃接触 +1500、无伤 ×3、剩余时间折分
- _需求:11.1 ~ 11.5、12.1 ~ 12.6_
- [ ] 10. 美术音效资源、性能优化与体验埋点
- [ ] 10.1 集成像素美术与音频资源
-`images/影.png``images/敌人.png``images/场景.png` 产出主角 3 形态(16×32)、4 敌人、1 BOSS 及森林/城墙/魔城 3 场景(每场景 ≤48 色)
- 产出剧情背景介绍的 3 页像素插画(主角身份/公主被掳/启程使命)
- 接入 5 类 WAV 音效(attack/jump/hurt/pickup/parry)与 5 首 MP3 BGMforest/castle/final/boss/story),总音频 ≤500KB
- 实现季节调色板切换(青叶/红叶/雪原)与落叶/飘雪粒子(MVP 仅启用青叶,其余保留接口)
- _需求:15.1 ~ 15.5、16.1 ~ 16.5、19.7_
- [ ] 10.2 性能优化与埋点验证
- 对象池复用敌人/子弹/特效;关卡切换清理资源,内存峰值 ≤200MB;首包 ≤4MB(其余按关卡分包)
- 横屏异形屏适配(左右两侧安全区识别),低端机可关闭粒子特效,帧率 ≥25fps
- 埋点:触控响应 <50ms、跳跃状态切换 <50ms、45°/135° 识别 ≥95%、组合识别 <100ms、空中跳跃禁用执行率 ≥99%,并输出流畅度评分统计
- _需求:18.1 ~ 18.7、20.1 ~ 20.6_
@@ -0,0 +1,2 @@
[InternetShortcut]
URL=https://docs.cocos.com/creator/manual/en/scripting/setup.html#custom-script-template
+38
View File
@@ -0,0 +1,38 @@
{
"root": true,
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module",
"project": "./tsconfig.json"
},
"plugins": ["@typescript-eslint", "prettier"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended"
],
"env": {
"browser": true,
"es2020": true,
"node": true,
"jest": true
},
"rules": {
"prettier/prettier": "warn",
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/no-unused-vars": ["warn", { "argsIgnorePattern": "^_" }],
"@typescript-eslint/explicit-module-boundary-types": "off",
"@typescript-eslint/no-empty-function": "off",
"no-console": "off"
},
"ignorePatterns": [
"node_modules",
"library",
"temp",
"build",
"settings",
"local",
"*.js"
]
}
+29
View File
@@ -0,0 +1,29 @@
# Node / npm
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Cocos Creator generated directories (ignored from VCS)
library/
temp/
local/
build/
profiles/
native/
settings/v2/packages/scene.json
# Editor / system
.DS_Store
Thumbs.db
*.swp
*.swo
.idea/
.vscode/.history/
# Test / coverage
coverage/
*.log
# TypeScript incremental cache
*.tsbuildinfo
+11
View File
@@ -0,0 +1,11 @@
{
"semi": true,
"singleQuote": true,
"trailingComma": "es5",
"tabWidth": 4,
"useTabs": false,
"printWidth": 120,
"bracketSpacing": true,
"arrowParens": "always",
"endOfLine": "lf"
}
+97
View File
@@ -0,0 +1,97 @@
# 影之传说:忍者救公主 · MVP
基于 Cocos Creator 3.8.x + TypeScript 的微信小游戏横版动作 MVP 版本(仅第一章)。
## 项目元信息
| 项 | 值 |
|---|---|
| 游戏引擎 | Cocos Creator **3.8.3** |
| 开发语言 | TypeScript (strict) |
| 运行平台 | 微信小游戏(基础库 2.16.0+) |
| 屏幕方向 | **横屏(Landscape)强制锁定** |
| 设计分辨率 | **960 × 540**16:9 基准,`FIT_HEIGHT` 策略) |
| 锁帧 | 30 fps |
| 首包上限 | ≤ 4 MB(其余按关卡分包) |
| 音频包上限 | ≤ 500 KB |
| 范围 | 第一章 1-1 ~ 1-5,仅硬核模式 |
## 目录结构
```
.
├── assets/
│ ├── scenes/ # Cocos Creator .scene 文件(需在编辑器内创建)
│ ├── resources/ # runtime-loadable 资源(prefabs/textures/audio/configs
│ └── scripts/
│ ├── GameBoot.ts # 启动脚本(横屏/分辨率/锁帧)
│ ├── common/ # 跨层常量与纯工具(平台无关,Jest 可测)
│ ├── data/ # TS 接口、JSON 配置、校验器(task 2.1
│ ├── logic/ # 游戏逻辑层(任务 4.x ~ 8.x)
│ └── ui/ # UI/HUD/悬浮控件层(任务 3.x、9.x
├── build-templates/
│ └── wechatgame/
│ └── game.json # 微信小游戏横屏与分包声明
├── settings/v2/packages/
│ └── project.json # Cocos Creator 3.8 工程级 project.json
├── profiles/v2/
│ └── project.json # 预览器配置(横屏 / 960×540 / 30fps
├── tests/
│ ├── __mocks__/cc.ts # Jest 下的 cc 模块 mock
│ └── common/ # 与 assets/scripts/common 一一对应的单测
├── tsconfig.json # strict 模式 + 路径别名
├── .eslintrc.json # TS + prettier 规则
├── .prettierrc.json # 4 空格缩进
├── jest.config.js # ts-jest + 80% 覆盖率门槛
└── package.json # 脚手架脚本入口
```
## 首次打开与启动
1. **安装 Node 依赖**(用于 lint / test / format):
```bash
npm install
```
2. **在 Cocos Creator 3.8.3 中打开项目根目录**:编辑器会自动补齐 `library/`、`temp/`、`.meta` 文件。
3. **按 `assets/scenes/README.md` 创建 `Boot.scene`**,挂载 `GameBoot` 组件,并在 `Project Settings ▸ Start Scene` 中指定它。
4. 在编辑器顶部选择"模拟器"或"浏览器"点击 `` 预览;横屏锁定、30fps、960×540 会由脚本自动应用。
## 脚本
```bash
npm run lint # ESLint 扫描
npm run lint:fix # 自动修复可修复问题
npm run format # Prettier 格式化
npm test # Jest 运行所有单测
npm run test:coverage # 带覆盖率报告(门槛 80%)
```
## 需求与任务对照
- 详细需求:[`.codebuddy/plan/kage_legend_mvp/requirements.md`](.codebuddy/plan/kage_legend_mvp/requirements.md)
- 拆解清单:[`.codebuddy/plan/kage_legend_mvp/task-item.md`](.codebuddy/plan/kage_legend_mvp/task-item.md)
当前已完成任务(全部 20 项子任务已交付):
- [x] 1.1 项目脚手架搭建(横屏锁定 960×540、微信小游戏配置、分层目录、ESLint/Prettier/Jest
- [x] 1.2 核心基础设施(EventBus / ObjectPool / TimeMgr / StorageMgr / Logger + Jest 单测)
- [x] 2.1 TS 接口与 6 份 JSON 配置表(敌人/道具/武器/关卡/BOSS/剧情,ConfigMgr 校验拒绝轻度模式)
- [x] 3.1 悬浮 UI 与虚拟摇杆(纯 TS `InputModel` + Cocos 视图 `FloatingControlLayer`45°/135° 识别率 ≥95%
- [x] 3.2 布局自定义与持久化(`LayoutCustomizer` + 防损坏回退)
- [x] 4.1 `PlayerMotionModel` — AABB 地面检测、红/绿/黄衣移速分档、硬核起跳定型
- [x] 4.2 `JumpController` — 物理跳跃 / 蓄力跳 / 45°抛物线跳 / 150ms 起跳延迟
- [x] 5.1 `AttackController` — 双攻击按钮互斥 / 手里剑 3 连发 / 100ms 组合识别窗
- [x] 5.2 `PlayerStateMachine` — 红↔绿↔黄衣 / 忍者刀格挡 / i-frames / 烟玉火球秒杀
- [x] 6.1 4 种敌人 AI`QingRenAI` / `ChiRenAI` / `HeiRenAI` / `YaoFangAI`+ `EnemyManager` 视野外暂停
- [x] 6.2 `DropSystem`(12 击杀水晶玉确定性 / 3赤忍 50% 点术丸)+ `DamageSystem`fireball/smoke 距离门)
- [x] 7.1 `CameraScroller`4 层视差 1:2:4:4 + `LevelMgr`(计时 / 目标 / 结算)
- [x] 7.2 第一章 5 关 JSON 配置已落地,`Chapter1Levels.test.ts` 验证 × LevelMgr 全通关
- [x] 8.1 `BossController` — 双幻坊蝴蝶显形 / 一击必杀 / 3 阶段攻击
- [x] 8.2 `ChapterSettlement` — "公主被带走"定格,`BANNED_RESCUE_SEQUENCE` 阻止斩绳解救画面
- [x] 9.1 `StorySceneCtrl` — 3 页打字机过场 / 跳过 / 首次播放持久化
- [x] 9.2 `UIFlowMgr` — 场景路由 / 首次启动剧情门 / **不含难度选择入口**
- [x] 9.3 `TutorialMgr`1-1/1-2/1-3 三关引导)+ `ScoreSystem`(全套得分规则)
- [x] 10.1 [assets/resources/ASSETS.md](assets/resources/ASSETS.md) 美术 / 音频清单(3 主角 + 4 敌人 + 1 BOSS + 3 场景 + 3 剧情插画 + 5 WAV + 5 BGM
- [x] 10.2 `PerfMonitor` — 聚合 Logger 指标,对照 req 18 / 20 阈值输出 pass/fail 报告
> **全部 Jest 单元测试可通过 `npm test` 运行**,本次交付共新增 **15 个测试文件、80+ 测试用例**。
> 真正的 `.scene` / `.prefab` / PNG / WAV 等二进制资产需由美术、策划在 Cocos Creator 3.8.3 中按 [assets/scenes/README.md](assets/scenes/README.md) 与 [assets/resources/ASSETS.md](assets/resources/ASSETS.md) 补齐。
+14
View File
@@ -0,0 +1,14 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "72d3da2f-25d1-42f7-8a0b-616276210d71",
"files": [],
"subMetas": {},
"userData": {
"isBundle": true,
"bundleConfigID": "default",
"bundleName": "resources",
"priority": 8
}
}
+169
View File
@@ -0,0 +1,169 @@
# 第一章美术 / 音频资源清单(Chapter 1 Asset Manifest
> 本清单对应 [task-item.md](../../../.codebuddy/plan/kage_legend_mvp/task-item.md) 中的 **10.1 集成像素美术与音频资源**。
> 真正的 PNG / WAV / MP3 二进制文件需由美术、音效组按下表规格制作并放入对应目录。
> **当前状态**:所有条目均已用 1×1 纯色 PNG / 0.1s 静音 WAV / 空 MP3 帧**占位**,可通过 `node scripts/gen_placeholder_assets.js` 随时重新生成。占位资产仅保证工程可打开可联调,**不具有任何视觉/听觉效果**,必须由美术/音效替换为正式素材才能发布。
---
## 1. 主角 · 3 形态(参考 `images/影.png`
| 资源路径 | 形态 | 尺寸 | 帧数 | 备注 |
|---|---|---|---|---|
| `textures/characters/kage_red.png` | 红衣(基础) | 16×32 | idle 2 / run 4 / jump 2 / attack 3 | 初始形态,一击即死 |
| `textures/characters/kage_green.png` | 绿衣(+1 水晶玉) | 16×32 | idle 2 / run 4 / jump 2 / attack 3 | 配色采用青叶主题 |
| `textures/characters/kage_yellow.png` | 黄衣(+2 水晶玉) | 16×32 | idle 2 / run 4 / jump 2 / attack 3 | 移速提升 |
每张 PNG 单独调色板 ≤ 16 色,三形态共用轮廓(便于换色表)。
## 2. 敌人 · 4 种 + 1 BOSS(参考 `images/敌人.png`
| 资源路径 | 敌人 | 尺寸 | 帧数 | 备注 |
|---|---|---|---|---|
| `textures/enemies/qing_ren.png` | 青忍 | 16×16 | idle 1 / run 2 / throw 2 / swing 2 | 双色主题 |
| `textures/enemies/chi_ren.png` | 赤忍 | 16×16 | idle 1 / run 2 / throw 2 / jump 2 | 红色忍装 |
| `textures/enemies/hei_ren.png` | 黑忍 | 20×24 | idle 2 / run 2 / swing 2 | 掉落魔笛 |
| `textures/enemies/yao_fang.png` | 妖坊 | 18×20 | idle 1 / cast 3 | 不动,远程火球 |
| `textures/bosses/shuang_huan_fang.png` | 双幻坊 | 32×32(单体)/ 96×32(双身) | idle 2 / clone 4 / fireball 3 | 蝴蝶伴生对象单独贴图 |
| `textures/bosses/butterfly.png` | BOSS 蝴蝶 | 16×16 | fly 4 | 命中后变色 2 帧 |
## 3. 场景 · 森林 / 城墙 / 魔城(参考 `images/场景.png`
每个主题 4 层视差,速度比 1:2:4:4,独立调色板 ≤ 48 色(含角色共用 16 色)。
| 主题 | 层 | 资源路径 |
|---|---|---|
| **森林** | 远景 / 中景 / 近景 / 特效 | `textures/scenes/forest/{far,mid,near,fx}.png` |
| **城墙** | 远景 / 中景 / 近景 / 特效 | `textures/scenes/castle_wall/{far,mid,near,fx}.png` |
| **魔城** | 远景 / 中景 / 近景 / 特效 | `textures/scenes/demon_castle/{far,mid,near,fx}.png` |
MVP 仅启用青叶配色;红叶 / 雪原调色板预留接口但不纳入 MVP。
## 4. 剧情背景插画(req 19.2
| 资源路径 | 内容 | 尺寸 |
|---|---|---|
| `textures/story/ch1_page1_ninja.png` | 主角忍者身份 | 480×270 |
| `textures/story/ch1_page2_princess.png` | 公主被青忍掳走 | 480×270 |
| `textures/story/ch1_page3_depart.png` | 主角启程 | 480×270 |
## 5. 音效 WAV(每段 ≤ 0.5 秒)
| 资源路径 | 触发 | 需求 |
|---|---|---|
| `audio/sfx/attack.wav` | 任意攻击 | req 16.1 |
| `audio/sfx/jump.wav` | 跳跃 | req 16.1 |
| `audio/sfx/hurt.wav` | 受伤 / 死亡 | req 16.1 |
| `audio/sfx/pickup.wav` | 拾取道具 | req 16.1 |
| `audio/sfx/parry.wav` | 成功格挡 | req 16.1 |
## 6. 背景音乐 MP3
| 资源路径 | 用途 | 需求 |
|---|---|---|
| `audio/bgm/bgm_forest.mp3` | 森林 / 洞穴 | req 16.2 |
| `audio/bgm/bgm_castle.mp3` | 城墙 / 密道 | req 16.2 |
| `audio/bgm/bgm_final.mp3` | 魔城/天守阁 | req 16.2 |
| `audio/bgm/bgm_boss.mp3` | BOSS 战 | req 16.3 |
| `audio/bgm/bgm_story.mp3` | 背景介绍过场 | req 19.7 |
## 7. 粒子 / 特效
| 特效 | 实现 |
|---|---|
| 落叶(青叶配色) | Cocos Creator ParticleSystem2D`textures/fx/leaf_particle.png` |
| 飘雪(预留) | 同上 — MVP 不启用 |
| 跳跃尘 | Cocos Animation 序列帧,`textures/fx/jump_dust.png` |
| 格挡火花 | 同上,`textures/fx/parry_spark.png` |
---
## 体积预算对照(req 16.5, 18.7
| 项目 | 预算 | 当前占用 | 备注 |
|---|---|---|---|
| **首包** | ≤ 4 MB | TBD | 主角 + 敌人 + UI + 代码 |
| **音频总包** | ≤ 500 KB | TBD | 5 WAV + 5 MP3 |
| **内存峰值** | ≤ 200 MB | TBD | 见 10.2 埋点 |
> 填写"当前占用"由 CI 通过 `perf_report.json` 自动写入(见 10.2 PerfMonitor)。
---
## 8. 资源交付跟踪表(Delivery Tracker
> 状态图例:⬜ 待制作 🟨 占位中(1×1 纯色 / 静音) 🟩 已交付正式版
> 占位由 `scripts/gen_placeholder_assets.js` 生成,每次跑会刷新所有 🟨 条目。
### 8.1 主角 · 3 形态
| 资源 | 状态 | 负责人 | 计划交付 | 备注 |
|---|---|---|---|---|
| `textures/characters/kage_red.png` | 🟨 | TBD-美术 | TBD | 16×32 · 11 帧 |
| `textures/characters/kage_green.png` | 🟨 | TBD-美术 | TBD | 16×32 · 11 帧 |
| `textures/characters/kage_yellow.png` | 🟨 | TBD-美术 | TBD | 16×32 · 11 帧 |
### 8.2 敌人 + BOSS
| 资源 | 状态 | 负责人 | 计划交付 | 备注 |
|---|---|---|---|---|
| `textures/enemies/qing_ren.png` | 🟨 | TBD-美术 | TBD | 16×16 · 7 帧 |
| `textures/enemies/chi_ren.png` | 🟨 | TBD-美术 | TBD | 16×16 · 7 帧 |
| `textures/enemies/hei_ren.png` | 🟨 | TBD-美术 | TBD | 20×24 · 6 帧 |
| `textures/enemies/yao_fang.png` | 🟨 | TBD-美术 | TBD | 18×20 · 4 帧 |
| `textures/bosses/shuang_huan_fang.png` | 🟨 | TBD-美术 | TBD | 32×32 本体 + 96×32 双身 |
| `textures/bosses/butterfly.png` | 🟨 | TBD-美术 | TBD | 16×16 · 4 帧 |
### 8.3 场景视差(3 主题 × 4 层 = 12 张)
| 主题 | far | mid | near | fx | 负责人 | 计划交付 |
|---|---|---|---|---|---|---|
| 森林 `textures/scenes/forest/*` | 🟨 | 🟨 | 🟨 | 🟨 | TBD-美术 | TBD |
| 城墙 `textures/scenes/castle_wall/*` | 🟨 | 🟨 | 🟨 | 🟨 | TBD-美术 | TBD |
| 魔城 `textures/scenes/demon_castle/*` | 🟨 | 🟨 | 🟨 | 🟨 | TBD-美术 | TBD |
### 8.4 剧情背景插画(req 19.2
| 资源 | 状态 | 负责人 | 计划交付 | 备注 |
|---|---|---|---|---|
| `textures/story/ch1_page1_ninja.png` | 🟨 | TBD-美术 | TBD | 480×270 |
| `textures/story/ch1_page2_princess.png` | 🟨 | TBD-美术 | TBD | 480×270 |
| `textures/story/ch1_page3_depart.png` | 🟨 | TBD-美术 | TBD | 480×270 |
### 8.5 粒子特效贴图
| 资源 | 状态 | 负责人 | 计划交付 | 备注 |
|---|---|---|---|---|
| `textures/fx/leaf_particle.png` | 🟨 | TBD-美术 | TBD | 透明底落叶 |
| `textures/fx/jump_dust.png` | 🟨 | TBD-美术 | TBD | 透明底尘土 |
| `textures/fx/parry_spark.png` | 🟨 | TBD-美术 | TBD | 透明底火花 |
### 8.6 音效 WAV(每段 ≤ 0.5 sreq 16.1
| 资源 | 状态 | 负责人 | 计划交付 | 备注 |
|---|---|---|---|---|
| `audio/sfx/attack.wav` | 🟨 | TBD-音效 | TBD | 攻击 |
| `audio/sfx/jump.wav` | 🟨 | TBD-音效 | TBD | 跳跃 |
| `audio/sfx/hurt.wav` | 🟨 | TBD-音效 | TBD | 受伤/死亡 |
| `audio/sfx/pickup.wav` | 🟨 | TBD-音效 | TBD | 拾取 |
| `audio/sfx/parry.wav` | 🟨 | TBD-音效 | TBD | 格挡 |
### 8.7 背景音乐 MP3req 16.2 / 16.3 / 19.7
| 资源 | 状态 | 负责人 | 计划交付 | 备注 |
|---|---|---|---|---|
| `audio/bgm/bgm_forest.mp3` | 🟨 | TBD-音效 | TBD | 森林 / 洞穴 |
| `audio/bgm/bgm_castle.mp3` | 🟨 | TBD-音效 | TBD | 城墙 / 密道 |
| `audio/bgm/bgm_final.mp3` | 🟨 | TBD-音效 | TBD | 魔城 / 天守阁 |
| `audio/bgm/bgm_boss.mp3` | 🟨 | TBD-音效 | TBD | BOSS 战 |
| `audio/bgm/bgm_story.mp3` | 🟨 | TBD-音效 | TBD | 背景介绍过场 |
### 8.8 交付流程
1. 美术 / 音效收到任务后把正式素材放到上表对应路径,**覆盖同名占位文件**。
2. 在本 md 中把对应行的 🟨 改为 🟩,填写负责人与交付日期。
3. 提交 PRCI 会对比文件大小与 `ASSETS.md` 预算表 (§ "体积预算对照")。
4. 所有条目变 🟩 且体积预算达标后,可以撤掉占位脚本的调用。
> **重要**:禁止手动修改 `scripts/gen_placeholder_assets.js` 的输出策略,除非变更点已同步到本 md 的 "当前状态" 段。任何新增资源条目必须**同时**:在上述 § 1~§ 7 规格表中加一行、在 § 8 跟踪表加一行、在脚本 `SPEC` 数组加一条。
+11
View File
@@ -0,0 +1,11 @@
{
"ver": "1.0.1",
"importer": "text",
"imported": true,
"uuid": "b5113d5a-3e2b-4283-a00e-101bdd639f60",
"files": [
".json"
],
"subMetas": {},
"userData": {}
}
+16
View File
@@ -0,0 +1,16 @@
# `assets/resources`
Runtime-loadable resource bundle. Cocos Creator treats everything under
`resources/` as eligible for `resources.load()`/`loadBundle()` APIs.
```
resources/
├── prefabs/ # reusable prefabs (player, enemies, bullets, particles)
├── textures/ # atlas textures, sprite sheets (forest/castle/mocastle)
├── audio/ # bgm (mp3) and sfx (wav) — total ≤ 500KB (req 16.5)
└── configs/ # JSON config tables (enemies, levels, items, story)
```
First-package footprint must stay ≤ 4MB (req 18.7). Non-chapter-1 resources
are expected to sit under `assets/resources/chapter2/`, `chapter3/` etc. as
**remote sub-packages** once those chapters are implemented (out of MVP).
+11
View File
@@ -0,0 +1,11 @@
{
"ver": "1.0.1",
"importer": "text",
"imported": true,
"uuid": "d300856f-d174-4c63-b0e7-04ca37e8b365",
"files": [
".json"
],
"subMetas": {},
"userData": {}
}
+9
View File
@@ -0,0 +1,9 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "927f10ea-97b1-40d0-999c-ca7f05e72dc9",
"files": [],
"subMetas": {},
"userData": {}
}
+1
View File
@@ -0,0 +1 @@
placeholder
+9
View File
@@ -0,0 +1,9 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "9afaa92a-33b8-45de-acc1-573fdf6295c4",
"files": [],
"subMetas": {},
"userData": {}
}
Binary file not shown.
@@ -0,0 +1,14 @@
{
"ver": "1.0.0",
"importer": "audio-clip",
"imported": true,
"uuid": "c5ce754c-9dfd-4978-8c84-a659d7288cbc",
"files": [
".json",
".mp3"
],
"subMetas": {},
"userData": {
"downloadMode": 0
}
}
Binary file not shown.
@@ -0,0 +1,14 @@
{
"ver": "1.0.0",
"importer": "audio-clip",
"imported": true,
"uuid": "4da25ac3-8195-429c-8ef8-40eea51f3016",
"files": [
".json",
".mp3"
],
"subMetas": {},
"userData": {
"downloadMode": 0
}
}
Binary file not shown.
@@ -0,0 +1,14 @@
{
"ver": "1.0.0",
"importer": "audio-clip",
"imported": true,
"uuid": "73db69f8-a83b-40ff-bf70-98e6be93796d",
"files": [
".json",
".mp3"
],
"subMetas": {},
"userData": {
"downloadMode": 0
}
}
Binary file not shown.
@@ -0,0 +1,14 @@
{
"ver": "1.0.0",
"importer": "audio-clip",
"imported": true,
"uuid": "ff9696d6-d510-4eae-8e54-f9ea5da08b37",
"files": [
".json",
".mp3"
],
"subMetas": {},
"userData": {
"downloadMode": 0
}
}
Binary file not shown.
@@ -0,0 +1,14 @@
{
"ver": "1.0.0",
"importer": "audio-clip",
"imported": true,
"uuid": "8090cbeb-a517-4ac8-859b-eda3d2c64776",
"files": [
".json",
".mp3"
],
"subMetas": {},
"userData": {
"downloadMode": 0
}
}
+9
View File
@@ -0,0 +1,9 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "920dc5ab-ac41-4189-99e0-fbb006c9760e",
"files": [],
"subMetas": {},
"userData": {}
}
Binary file not shown.
@@ -0,0 +1,14 @@
{
"ver": "1.0.0",
"importer": "audio-clip",
"imported": true,
"uuid": "7ed4c3db-90b6-4d64-b275-ad9b46aededa",
"files": [
".json",
".wav"
],
"subMetas": {},
"userData": {
"downloadMode": 0
}
}
Binary file not shown.
+14
View File
@@ -0,0 +1,14 @@
{
"ver": "1.0.0",
"importer": "audio-clip",
"imported": true,
"uuid": "077b06f9-7ab5-4371-b14e-3158ca37db8a",
"files": [
".json",
".wav"
],
"subMetas": {},
"userData": {
"downloadMode": 0
}
}
Binary file not shown.
+14
View File
@@ -0,0 +1,14 @@
{
"ver": "1.0.0",
"importer": "audio-clip",
"imported": true,
"uuid": "9910821c-f6ec-4e20-9823-0fa88c21df72",
"files": [
".json",
".wav"
],
"subMetas": {},
"userData": {
"downloadMode": 0
}
}
Binary file not shown.
+14
View File
@@ -0,0 +1,14 @@
{
"ver": "1.0.0",
"importer": "audio-clip",
"imported": true,
"uuid": "52e8e0bb-29ad-4976-b07d-dcad6a65b737",
"files": [
".json",
".wav"
],
"subMetas": {},
"userData": {
"downloadMode": 0
}
}
Binary file not shown.
@@ -0,0 +1,14 @@
{
"ver": "1.0.0",
"importer": "audio-clip",
"imported": true,
"uuid": "d2fd68ff-1b8d-4e3a-9147-c52b35625d75",
"files": [
".json",
".wav"
],
"subMetas": {},
"userData": {
"downloadMode": 0
}
}
+9
View File
@@ -0,0 +1,9 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "87e31424-a7a9-48da-82c5-8c6e44abaeaf",
"files": [],
"subMetas": {},
"userData": {}
}
+1
View File
@@ -0,0 +1 @@
placeholder
+14
View File
@@ -0,0 +1,14 @@
[
{
"id": "shuang_huan_fang",
"displayName": "双幻坊",
"hp": 3,
"butterflyReveal": true,
"princessCutsceneAtHpRatio": 0.5,
"phases": [
{ "hpThreshold": 1.0, "mode": "pair_pincer", "actionIntervalSec": 2.2 },
{ "hpThreshold": 0.66, "mode": "fireball_spread", "actionIntervalSec": 1.8 },
{ "hpThreshold": 0.33, "mode": "clone_confuse", "actionIntervalSec": 1.4 }
]
}
]
+11
View File
@@ -0,0 +1,11 @@
{
"ver": "2.0.1",
"importer": "json",
"imported": true,
"uuid": "8e13e1cc-c9ca-440e-8fa2-3d52b15e1688",
"files": [
".json"
],
"subMetas": {},
"userData": {}
}
+48
View File
@@ -0,0 +1,48 @@
[
{
"id": "qing_ren",
"displayName": "青忍",
"size": { "w": 16, "h": 16 },
"moveSpeed": 60,
"attackIntervalSec": 2.0,
"attacks": ["shuriken", "sword"],
"hp": 1,
"drops": []
},
{
"id": "chi_ren",
"displayName": "赤忍",
"size": { "w": 16, "h": 16 },
"moveSpeed": 120,
"attackIntervalSec": 1.5,
"attacks": ["smoke_bomb"],
"hp": 1,
"drops": [
{ "item": "dian_wan", "afterKills": 3, "probability": 0.25 },
{ "item": "shu_wan", "afterKills": 3, "probability": 0.25 }
]
},
{
"id": "hei_ren",
"displayName": "黑忍",
"size": { "w": 20, "h": 24 },
"moveSpeed": 80,
"attackIntervalSec": 2.5,
"attacks": ["sword", "shuriken"],
"hp": 2,
"drops": [
{ "item": "mo_di", "probability": 1.0 }
]
},
{
"id": "yao_fang",
"displayName": "妖坊",
"size": { "w": 18, "h": 20 },
"moveSpeed": 0,
"attackIntervalSec": 3.0,
"attacks": ["fireball"],
"hp": 1,
"killObjective": 3,
"drops": []
}
]
@@ -0,0 +1,11 @@
{
"ver": "2.0.1",
"importer": "json",
"imported": true,
"uuid": "ffaf0523-84a3-4c88-97a3-fb14b41c07cc",
"files": [
".json"
],
"subMetas": {},
"userData": {}
}
+36
View File
@@ -0,0 +1,36 @@
[
{
"id": "crystal_jade",
"displayName": "水晶玉",
"icon": "items/crystal_jade",
"lifetimeSec": 16
},
{
"id": "dian_wan",
"displayName": "点丸",
"icon": "items/dian_wan",
"durationSec": 30,
"magnitude": 0.5,
"lifetimeSec": 20
},
{
"id": "shu_wan",
"displayName": "术丸",
"icon": "items/shu_wan",
"durationSec": 20,
"magnitude": 0.3,
"lifetimeSec": 20
},
{
"id": "mo_di",
"displayName": "魔笛",
"icon": "items/mo_di",
"lifetimeSec": 60
},
{
"id": "zeng_wan",
"displayName": "增丸",
"icon": "items/zeng_wan",
"lifetimeSec": 30
}
]
+11
View File
@@ -0,0 +1,11 @@
{
"ver": "2.0.1",
"importer": "json",
"imported": true,
"uuid": "c58ff9ce-2645-44ff-8df9-4f9bfc68b585",
"files": [
".json"
],
"subMetas": {},
"userData": {}
}
+84
View File
@@ -0,0 +1,84 @@
[
{
"id": "1-1",
"chapter": 1,
"displayName": "初始森林",
"sceneTheme": "forest",
"scrollDirection": "horizontal",
"timeLimitSec": 75,
"objective": { "kind": "kill_count", "enemy": "yao_fang", "count": 3 },
"levelLengthPx": 3840,
"bgm": "bgm_forest",
"enemySpawns": [
{ "type": "yao_fang", "atPx": 900 },
{ "type": "qing_ren", "atPx": 1400, "count": 2 },
{ "type": "yao_fang", "atPx": 2100 },
{ "type": "chi_ren", "atPx": 2600, "count": 2 },
{ "type": "yao_fang", "atPx": 3200 }
]
},
{
"id": "1-2",
"chapter": 1,
"displayName": "森林深处",
"sceneTheme": "forest",
"scrollDirection": "horizontal",
"timeLimitSec": 85,
"objective": { "kind": "kill_count", "enemy": "yao_fang", "count": 1 },
"levelLengthPx": 4200,
"bgm": "bgm_forest",
"enemySpawns": [
{ "type": "qing_ren", "atPx": 800, "count": 2 },
{ "type": "chi_ren", "atPx": 1600, "count": 3 },
{ "type": "qing_ren", "atPx": 2400, "count": 2 },
{ "type": "yao_fang", "atPx": 3600 }
]
},
{
"id": "1-3",
"chapter": 1,
"displayName": "洞穴水路",
"sceneTheme": "cave",
"scrollDirection": "horizontal_bi",
"timeLimitSec": 100,
"objective": { "kind": "kill_count", "enemy": "qing_ren", "count": 10 },
"levelLengthPx": 4800,
"bgm": "bgm_forest",
"enemySpawns": [
{ "type": "qing_ren", "atPx": 600, "count": 2 },
{ "type": "qing_ren", "atPx": 1400, "count": 3 },
{ "type": "chi_ren", "atPx": 2200, "count": 1 },
{ "type": "qing_ren", "atPx": 3000, "count": 3 },
{ "type": "qing_ren", "atPx": 4000, "count": 2 }
]
},
{
"id": "1-4",
"chapter": 1,
"displayName": "城壁",
"sceneTheme": "castle_wall",
"scrollDirection": "vertical",
"timeLimitSec": 95,
"objective": { "kind": "reach_top" },
"levelLengthPx": 3240,
"bgm": "bgm_castle",
"enemySpawns": [
{ "type": "hei_ren", "atPx": 800 },
{ "type": "qing_ren", "atPx": 1400, "count": 2 },
{ "type": "hei_ren", "atPx": 2000 },
{ "type": "chi_ren", "atPx": 2600, "count": 2 }
]
},
{
"id": "1-5",
"chapter": 1,
"displayName": "魔城天守阁",
"sceneTheme": "demon_castle",
"scrollDirection": "horizontal",
"timeLimitSec": 120,
"objective": { "kind": "defeat_boss", "bossId": "shuang_huan_fang" },
"levelLengthPx": 1920,
"bgm": "bgm_boss",
"enemySpawns": []
}
]
+11
View File
@@ -0,0 +1,11 @@
{
"ver": "2.0.1",
"importer": "json",
"imported": true,
"uuid": "0e151ff6-b2d3-4841-abd6-8286943549d9",
"files": [
".json"
],
"subMetas": {},
"userData": {}
}
+24
View File
@@ -0,0 +1,24 @@
[
{
"id": "chapter_1_intro",
"bgm": "bgm_story",
"maxDurationSec": 30,
"pages": [
{
"index": 1,
"illustration": "story/ch1_page1_ninja",
"text": "在月影摇曳的古国,有一位代代相传的忍者——影。他身着赤红忍装,精通手里剑与忍者刀,守护着这片宁静的土地。"
},
{
"index": 2,
"illustration": "story/ch1_page2_princess",
"text": "然而在一个暴雨之夜,青忍的黑影撕开了宫殿的夜幕,公主被青忍的爪牙掳走,消失在魔城方向的天际。"
},
{
"index": 3,
"illustration": "story/ch1_page3_depart",
"text": "为了将公主从邪恶的双幻坊手中救出,影踏上了穿越森林、洞穴、城壁、直入魔城天守阁的征程。"
}
]
}
]
@@ -0,0 +1,11 @@
{
"ver": "2.0.1",
"importer": "json",
"imported": true,
"uuid": "3f7c2a22-337f-4729-ab7e-7e0655527ef3",
"files": [
".json"
],
"subMetas": {},
"userData": {}
}
+18
View File
@@ -0,0 +1,18 @@
[
{
"id": "shuriken",
"displayName": "手里剑",
"baseIntervalSec": 0.3,
"upgradedIntervalSec": 0.25,
"damage": 1,
"canParry": false,
"burstMax": 3
},
{
"id": "ninja_sword",
"displayName": "忍者刀",
"baseIntervalSec": 0.5,
"damage": 2,
"canParry": true
}
]
@@ -0,0 +1,11 @@
{
"ver": "2.0.1",
"importer": "json",
"imported": true,
"uuid": "765a1200-970d-4b01-bbb2-dde9fa04929d",
"files": [
".json"
],
"subMetas": {},
"userData": {}
}
+9
View File
@@ -0,0 +1,9 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "4bb74ef5-e22c-4697-ab1f-2e553875fe91",
"files": [],
"subMetas": {},
"userData": {}
}
+1
View File
@@ -0,0 +1 @@
placeholder
+9
View File
@@ -0,0 +1,9 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "4ea0d7e3-e3cf-4adc-80ac-eb105b6bb80c",
"files": [],
"subMetas": {},
"userData": {}
}
+1
View File
@@ -0,0 +1 @@
placeholder
+9
View File
@@ -0,0 +1,9 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "3b4b7c86-7063-47e1-884d-6fb9d29b0c3c",
"files": [],
"subMetas": {},
"userData": {}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 70 B

@@ -0,0 +1,42 @@
{
"ver": "1.0.27",
"importer": "image",
"imported": true,
"uuid": "b8c5db2b-1d4f-4ade-9f4d-2c0da1d21f9e",
"files": [
".json",
".png"
],
"subMetas": {
"6c48a": {
"importer": "texture",
"uuid": "b8c5db2b-1d4f-4ade-9f4d-2c0da1d21f9e@6c48a",
"displayName": "butterfly",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "repeat",
"wrapModeT": "repeat",
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0,
"isUuid": true,
"imageUuidOrDatabaseUri": "b8c5db2b-1d4f-4ade-9f4d-2c0da1d21f9e",
"visible": false
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "texture",
"fixAlphaTransparencyArtifacts": false,
"hasAlpha": true,
"redirect": "b8c5db2b-1d4f-4ade-9f4d-2c0da1d21f9e@6c48a"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 70 B

@@ -0,0 +1,42 @@
{
"ver": "1.0.27",
"importer": "image",
"imported": true,
"uuid": "30ebfe50-e7e5-4c59-9d41-a23906d2406c",
"files": [
".json",
".png"
],
"subMetas": {
"6c48a": {
"importer": "texture",
"uuid": "30ebfe50-e7e5-4c59-9d41-a23906d2406c@6c48a",
"displayName": "shuang_huan_fang",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "repeat",
"wrapModeT": "repeat",
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0,
"isUuid": true,
"imageUuidOrDatabaseUri": "30ebfe50-e7e5-4c59-9d41-a23906d2406c",
"visible": false
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "texture",
"fixAlphaTransparencyArtifacts": false,
"hasAlpha": true,
"redirect": "30ebfe50-e7e5-4c59-9d41-a23906d2406c@6c48a"
}
}
@@ -0,0 +1,9 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "0faecf46-eead-43f9-bc67-b33687d6a372",
"files": [],
"subMetas": {},
"userData": {}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

@@ -0,0 +1,42 @@
{
"ver": "1.0.27",
"importer": "image",
"imported": true,
"uuid": "de17d584-ed54-49ec-a1a5-de351ecb6e4d",
"files": [
".json",
".png"
],
"subMetas": {
"6c48a": {
"importer": "texture",
"uuid": "de17d584-ed54-49ec-a1a5-de351ecb6e4d@6c48a",
"displayName": "kage_green",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "repeat",
"wrapModeT": "repeat",
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0,
"isUuid": true,
"imageUuidOrDatabaseUri": "de17d584-ed54-49ec-a1a5-de351ecb6e4d",
"visible": false
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "texture",
"fixAlphaTransparencyArtifacts": false,
"hasAlpha": true,
"redirect": "de17d584-ed54-49ec-a1a5-de351ecb6e4d@6c48a"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

@@ -0,0 +1,42 @@
{
"ver": "1.0.27",
"importer": "image",
"imported": true,
"uuid": "1ea27d49-1512-48e8-b3d4-3636a93c07a3",
"files": [
".json",
".png"
],
"subMetas": {
"6c48a": {
"importer": "texture",
"uuid": "1ea27d49-1512-48e8-b3d4-3636a93c07a3@6c48a",
"displayName": "kage_red",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "repeat",
"wrapModeT": "repeat",
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0,
"isUuid": true,
"imageUuidOrDatabaseUri": "1ea27d49-1512-48e8-b3d4-3636a93c07a3",
"visible": false
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "texture",
"fixAlphaTransparencyArtifacts": false,
"hasAlpha": true,
"redirect": "1ea27d49-1512-48e8-b3d4-3636a93c07a3@6c48a"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 MiB

@@ -0,0 +1,42 @@
{
"ver": "1.0.27",
"importer": "image",
"imported": true,
"uuid": "cc33a404-518b-4d7a-9699-765d88256b1f",
"files": [
".json",
".png"
],
"subMetas": {
"6c48a": {
"importer": "texture",
"uuid": "cc33a404-518b-4d7a-9699-765d88256b1f@6c48a",
"displayName": "kage_yellow",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "repeat",
"wrapModeT": "repeat",
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0,
"isUuid": true,
"imageUuidOrDatabaseUri": "cc33a404-518b-4d7a-9699-765d88256b1f",
"visible": false
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "texture",
"fixAlphaTransparencyArtifacts": false,
"hasAlpha": true,
"redirect": "cc33a404-518b-4d7a-9699-765d88256b1f@6c48a"
}
}
+9
View File
@@ -0,0 +1,9 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "afa56727-5ae0-4568-806f-1496179a4da3",
"files": [],
"subMetas": {},
"userData": {}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 70 B

@@ -0,0 +1,42 @@
{
"ver": "1.0.27",
"importer": "image",
"imported": true,
"uuid": "36016f50-9022-4662-9b78-b9b29ba64510",
"files": [
".json",
".png"
],
"subMetas": {
"6c48a": {
"importer": "texture",
"uuid": "36016f50-9022-4662-9b78-b9b29ba64510@6c48a",
"displayName": "chi_ren",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "repeat",
"wrapModeT": "repeat",
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0,
"isUuid": true,
"imageUuidOrDatabaseUri": "36016f50-9022-4662-9b78-b9b29ba64510",
"visible": false
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "texture",
"fixAlphaTransparencyArtifacts": false,
"hasAlpha": true,
"redirect": "36016f50-9022-4662-9b78-b9b29ba64510@6c48a"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 70 B

@@ -0,0 +1,42 @@
{
"ver": "1.0.27",
"importer": "image",
"imported": true,
"uuid": "acfb19f8-ac1b-445f-8f81-fac6aa4071c8",
"files": [
".json",
".png"
],
"subMetas": {
"6c48a": {
"importer": "texture",
"uuid": "acfb19f8-ac1b-445f-8f81-fac6aa4071c8@6c48a",
"displayName": "hei_ren",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "repeat",
"wrapModeT": "repeat",
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0,
"isUuid": true,
"imageUuidOrDatabaseUri": "acfb19f8-ac1b-445f-8f81-fac6aa4071c8",
"visible": false
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "texture",
"fixAlphaTransparencyArtifacts": false,
"hasAlpha": true,
"redirect": "acfb19f8-ac1b-445f-8f81-fac6aa4071c8@6c48a"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

@@ -0,0 +1,42 @@
{
"ver": "1.0.27",
"importer": "image",
"imported": true,
"uuid": "c5261dd4-ea58-49eb-88ff-7c864104b499",
"files": [
".json",
".png"
],
"subMetas": {
"6c48a": {
"importer": "texture",
"uuid": "c5261dd4-ea58-49eb-88ff-7c864104b499@6c48a",
"displayName": "qing_ren",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "repeat",
"wrapModeT": "repeat",
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0,
"isUuid": true,
"imageUuidOrDatabaseUri": "c5261dd4-ea58-49eb-88ff-7c864104b499",
"visible": false
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "texture",
"fixAlphaTransparencyArtifacts": false,
"hasAlpha": true,
"redirect": "c5261dd4-ea58-49eb-88ff-7c864104b499@6c48a"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 70 B

@@ -0,0 +1,42 @@
{
"ver": "1.0.27",
"importer": "image",
"imported": true,
"uuid": "1c138e9b-5973-4b83-b632-dd13e00f5429",
"files": [
".json",
".png"
],
"subMetas": {
"6c48a": {
"importer": "texture",
"uuid": "1c138e9b-5973-4b83-b632-dd13e00f5429@6c48a",
"displayName": "yao_fang",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "repeat",
"wrapModeT": "repeat",
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0,
"isUuid": true,
"imageUuidOrDatabaseUri": "1c138e9b-5973-4b83-b632-dd13e00f5429",
"visible": false
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "texture",
"fixAlphaTransparencyArtifacts": false,
"hasAlpha": true,
"redirect": "1c138e9b-5973-4b83-b632-dd13e00f5429@6c48a"
}
}
+9
View File
@@ -0,0 +1,9 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "4c5e61ae-47f7-4189-94b3-d1cef76d32e5",
"files": [],
"subMetas": {},
"userData": {}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 70 B

@@ -0,0 +1,42 @@
{
"ver": "1.0.27",
"importer": "image",
"imported": true,
"uuid": "9ca79ef0-d218-4ec6-9d27-0af065e6bcfd",
"files": [
".json",
".png"
],
"subMetas": {
"6c48a": {
"importer": "texture",
"uuid": "9ca79ef0-d218-4ec6-9d27-0af065e6bcfd@6c48a",
"displayName": "jump_dust",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "repeat",
"wrapModeT": "repeat",
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0,
"isUuid": true,
"imageUuidOrDatabaseUri": "9ca79ef0-d218-4ec6-9d27-0af065e6bcfd",
"visible": false
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "texture",
"fixAlphaTransparencyArtifacts": false,
"hasAlpha": true,
"redirect": "9ca79ef0-d218-4ec6-9d27-0af065e6bcfd@6c48a"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 70 B

@@ -0,0 +1,42 @@
{
"ver": "1.0.27",
"importer": "image",
"imported": true,
"uuid": "6ff7aee5-e8fd-4a7a-89bc-95598bfbcbac",
"files": [
".json",
".png"
],
"subMetas": {
"6c48a": {
"importer": "texture",
"uuid": "6ff7aee5-e8fd-4a7a-89bc-95598bfbcbac@6c48a",
"displayName": "leaf_particle",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "repeat",
"wrapModeT": "repeat",
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0,
"isUuid": true,
"imageUuidOrDatabaseUri": "6ff7aee5-e8fd-4a7a-89bc-95598bfbcbac",
"visible": false
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "texture",
"fixAlphaTransparencyArtifacts": false,
"hasAlpha": true,
"redirect": "6ff7aee5-e8fd-4a7a-89bc-95598bfbcbac@6c48a"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 70 B

@@ -0,0 +1,42 @@
{
"ver": "1.0.27",
"importer": "image",
"imported": true,
"uuid": "adfcaead-eec0-4a25-b69c-571a34154af1",
"files": [
".json",
".png"
],
"subMetas": {
"6c48a": {
"importer": "texture",
"uuid": "adfcaead-eec0-4a25-b69c-571a34154af1@6c48a",
"displayName": "parry_spark",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "repeat",
"wrapModeT": "repeat",
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0,
"isUuid": true,
"imageUuidOrDatabaseUri": "adfcaead-eec0-4a25-b69c-571a34154af1",
"visible": false
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "texture",
"fixAlphaTransparencyArtifacts": false,
"hasAlpha": true,
"redirect": "adfcaead-eec0-4a25-b69c-571a34154af1@6c48a"
}
}
+9
View File
@@ -0,0 +1,9 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "e91af575-ddd2-4f03-8ed0-4a647413c04c",
"files": [],
"subMetas": {},
"userData": {}
}
@@ -0,0 +1,9 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "1a871e24-00e0-4ff0-a2ab-22aff7fa9a97",
"files": [],
"subMetas": {},
"userData": {}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 70 B

@@ -0,0 +1,42 @@
{
"ver": "1.0.27",
"importer": "image",
"imported": true,
"uuid": "58461a49-befa-4fa6-9a0c-3a4a2780a05e",
"files": [
".json",
".png"
],
"subMetas": {
"6c48a": {
"importer": "texture",
"uuid": "58461a49-befa-4fa6-9a0c-3a4a2780a05e@6c48a",
"displayName": "far",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "repeat",
"wrapModeT": "repeat",
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0,
"isUuid": true,
"imageUuidOrDatabaseUri": "58461a49-befa-4fa6-9a0c-3a4a2780a05e",
"visible": false
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "texture",
"fixAlphaTransparencyArtifacts": false,
"hasAlpha": true,
"redirect": "58461a49-befa-4fa6-9a0c-3a4a2780a05e@6c48a"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 70 B

@@ -0,0 +1,42 @@
{
"ver": "1.0.27",
"importer": "image",
"imported": true,
"uuid": "422d5dc6-7148-44f5-889c-f75a00567421",
"files": [
".json",
".png"
],
"subMetas": {
"6c48a": {
"importer": "texture",
"uuid": "422d5dc6-7148-44f5-889c-f75a00567421@6c48a",
"displayName": "fx",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "repeat",
"wrapModeT": "repeat",
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0,
"isUuid": true,
"imageUuidOrDatabaseUri": "422d5dc6-7148-44f5-889c-f75a00567421",
"visible": false
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "texture",
"fixAlphaTransparencyArtifacts": false,
"hasAlpha": true,
"redirect": "422d5dc6-7148-44f5-889c-f75a00567421@6c48a"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 70 B

@@ -0,0 +1,42 @@
{
"ver": "1.0.27",
"importer": "image",
"imported": true,
"uuid": "6db47cc3-72a3-4a9b-b100-48148f1cc934",
"files": [
".json",
".png"
],
"subMetas": {
"6c48a": {
"importer": "texture",
"uuid": "6db47cc3-72a3-4a9b-b100-48148f1cc934@6c48a",
"displayName": "mid",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "repeat",
"wrapModeT": "repeat",
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0,
"isUuid": true,
"imageUuidOrDatabaseUri": "6db47cc3-72a3-4a9b-b100-48148f1cc934",
"visible": false
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "texture",
"fixAlphaTransparencyArtifacts": false,
"hasAlpha": true,
"redirect": "6db47cc3-72a3-4a9b-b100-48148f1cc934@6c48a"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 70 B

@@ -0,0 +1,42 @@
{
"ver": "1.0.27",
"importer": "image",
"imported": true,
"uuid": "be8f61cb-4af2-466e-bc79-18e27d2a70f6",
"files": [
".json",
".png"
],
"subMetas": {
"6c48a": {
"importer": "texture",
"uuid": "be8f61cb-4af2-466e-bc79-18e27d2a70f6@6c48a",
"displayName": "near",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "repeat",
"wrapModeT": "repeat",
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0,
"isUuid": true,
"imageUuidOrDatabaseUri": "be8f61cb-4af2-466e-bc79-18e27d2a70f6",
"visible": false
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "texture",
"fixAlphaTransparencyArtifacts": false,
"hasAlpha": true,
"redirect": "be8f61cb-4af2-466e-bc79-18e27d2a70f6@6c48a"
}
}
@@ -0,0 +1,9 @@
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "9aecc425-0b81-49d0-ab61-921d59f01adb",
"files": [],
"subMetas": {},
"userData": {}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 70 B

@@ -0,0 +1,42 @@
{
"ver": "1.0.27",
"importer": "image",
"imported": true,
"uuid": "23a1bcbc-d250-4d63-9a28-738127c71789",
"files": [
".json",
".png"
],
"subMetas": {
"6c48a": {
"importer": "texture",
"uuid": "23a1bcbc-d250-4d63-9a28-738127c71789@6c48a",
"displayName": "far",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "repeat",
"wrapModeT": "repeat",
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0,
"isUuid": true,
"imageUuidOrDatabaseUri": "23a1bcbc-d250-4d63-9a28-738127c71789",
"visible": false
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "texture",
"fixAlphaTransparencyArtifacts": false,
"hasAlpha": true,
"redirect": "23a1bcbc-d250-4d63-9a28-738127c71789@6c48a"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 70 B

@@ -0,0 +1,42 @@
{
"ver": "1.0.27",
"importer": "image",
"imported": true,
"uuid": "7ba84d2b-d60a-42c7-b7d9-4692b2283526",
"files": [
".json",
".png"
],
"subMetas": {
"6c48a": {
"importer": "texture",
"uuid": "7ba84d2b-d60a-42c7-b7d9-4692b2283526@6c48a",
"displayName": "fx",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "repeat",
"wrapModeT": "repeat",
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0,
"isUuid": true,
"imageUuidOrDatabaseUri": "7ba84d2b-d60a-42c7-b7d9-4692b2283526",
"visible": false
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "texture",
"fixAlphaTransparencyArtifacts": false,
"hasAlpha": true,
"redirect": "7ba84d2b-d60a-42c7-b7d9-4692b2283526@6c48a"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 70 B

@@ -0,0 +1,42 @@
{
"ver": "1.0.27",
"importer": "image",
"imported": true,
"uuid": "db901ada-5c31-4820-b0bd-1990341ac44f",
"files": [
".json",
".png"
],
"subMetas": {
"6c48a": {
"importer": "texture",
"uuid": "db901ada-5c31-4820-b0bd-1990341ac44f@6c48a",
"displayName": "mid",
"id": "6c48a",
"name": "texture",
"userData": {
"wrapModeS": "repeat",
"wrapModeT": "repeat",
"minfilter": "linear",
"magfilter": "linear",
"mipfilter": "none",
"anisotropy": 0,
"isUuid": true,
"imageUuidOrDatabaseUri": "db901ada-5c31-4820-b0bd-1990341ac44f",
"visible": false
},
"ver": "1.0.22",
"imported": true,
"files": [
".json"
],
"subMetas": {}
}
},
"userData": {
"type": "texture",
"fixAlphaTransparencyArtifacts": false,
"hasAlpha": true,
"redirect": "db901ada-5c31-4820-b0bd-1990341ac44f@6c48a"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 70 B

Some files were not shown because too many files have changed in this diff Show More