# 崩坏童话:蜜糖村(网页版) > 纯单机网页游戏 · Phaser 3 + TypeScript + Vite · 无后端、无存档、无 localStorage,浏览器打开即玩。 一个看起来百分之百治愈的像素童话村庄,实际是一场情绪疗程的沉浸幻境。玩家越"幸福",世界越饱和、越甜、越不对劲;通往真相的路,恰恰是那些系统禁止的悲伤。 ## 启动方式 需要 Node.js 18+。 ```bash npm install # 安装依赖 npm run dev # 开发模式(http://localhost:5173) npm run build # 产出纯静态 dist/ npm run preview # 本地预览构建产物(http://localhost:4173) ``` `npm run build` 产出纯静态 `dist/`,可直接用任意静态服务器托管;`npm run preview` 本地游玩。 ## 按键操作 | 按键 | 功能 | |---|---| | `W` `A` `S` `D` / 方向键 | 移动(四向动画 + 待机帧) | | `E` / `空格` / `回车` | 交互 / 推进对话 / 选择 | | `1` `2` `3` | 对话选项(温柔 / 迟疑 / 否定) | | `` ` ``(反引号) | 开关 Debug 面板 | ## Debug 面板(服务验收) 运行中按反引号键 `` ` `` 开关。默认关闭,关闭时无任何 UI 痕迹,不影响正常游玩。 功能: - 直接设置幸福值(10 / 40 / 70 / 90 / 100,分别对应 S0/S1/S2/S3/S4) - 切换觉知值(0 / 50 / 100) - 切换当前日(1–7 循环) - 置齐全部线索(C1–C9) - 传送到任意场景(小屋/广场/面包房/杂货店/诊所/湖畔/花田/古井/雾墙) - 强制触发四个结局之一(E1 糖衣 / E2 回收 / E3 苏醒 / E4 静默) ## 游玩说明 - 开局输入名字(留空默认「小满」)。 - 七日流程:晨起 → 公告板接任务 → 完成任务/自由活动 → 黄昏钟声 → 回屋睡觉 → 梦境过场 → 次日。 - 完整流程约 25–35 分钟,含 4 个结局。 - 幸福值以左上角向日葵表盘表示(12 片花瓣),全程不显示数字。满格后花心浮现黑籽。 ## 技术架构(PRD §12) - **Phaser 3 + TypeScript + Vite**。逻辑分辨率 320×180,整数倍放大居中,`pixelArt: true`,禁用纹理平滑。 - 场景:`BootScene`(加载)→ `TitleScene`(标题/输入名字)→ 各地图 Scene + 常驻 `UIScene`(对话框、向日葵表盘、提示)→ `EndingScene`;另 `DebugScene`。 - `CorruptionDirector`(`src/systems/CorruptionDirector.ts`):普通 TS 单例 + 事件发射器,持有幸福/觉知/日期/任务标记/线索集合/侵蚀阶段,是全部状态与视听参数的**唯一真源**。 - 饱和度与晕影用 Phaser 相机 postFX(`SaturationPostFX`),负片闪帧用单帧白色覆盖切换。 - BGM 与音效按 §6.6 用 Web Audio 程序合成(方波主旋律 + 三角波低音 8 小节循环),playbackRate 与 BiquadFilter 低通由 `CorruptionDirector` 驱动。**无外部音频文件**。 - 无 localStorage、无外部网络请求、无外部音频/字体文件。 ## 素材与地图制作流程(全部本项目内自制,无外部资产) ### 像素素材(Aseprite) 所有像素素材由 Aseprite 命令行 + Lua 脚本程序化绘制,脚本位于 `tools/`: | 脚本 | 产物 | 说明 | |---|---|---| | `tools/gen_tileset.lua` | `assets/tilesets/tileset.png`(128×128,64 个 16×16 瓦片) | 草地/石板路/湖水/花丛/莓果丛/树/房屋墙顶门/室内地板/家具(床/柜台/烤炉/货架/桌椅)/井/雾/白色层墙地等 | | `tools/gen_player.lua` | `assets/sprites/player.png`(64×96) | 主角 16×24/帧,4 朝向 × 4 帧行走(walk-down/up/left/right),第 1 帧兼待机 | | `tools/gen_portraits.lua` | `assets/sprites/portraits.png`(624×24) | 对话头像:主角微笑 + E3「真实的脸」;7 个具名 NPC 各 3 档表情(smile/flat/off);双子鸟;5 个群演 | | `tools/gen_npc.lua` | `assets/sprites/npc.png`(400×24) | NPC 场景立绘 16×24 ×3 档;双子鸟 2 帧张嘴动画;5 个群演 | 重新生成素材(需本机 Aseprite,路径 `/Applications/Aseprite.app/Contents/MacOS/aseprite`): ```bash "/Applications/Aseprite.app/Contents/MacOS/aseprite" -b --script tools/gen_tileset.lua "/Applications/Aseprite.app/Contents/MacOS/aseprite" -b --script tools/gen_player.lua "/Applications/Aseprite.app/Contents/MacOS/aseprite" -b --script tools/gen_portraits.lua "/Applications/Aseprite.app/Contents/MacOS/aseprite" -b --script tools/gen_npc.lua ``` ### 地图(Tiled Map Editor) 10 个场景地图为标准 Tiled JSON 格式(`assets/maps/*.json`),由 `tools/gen_maps.cjs` 程序化生成;瓦片集描述符由 `tools/gen_tileset_json.cjs` 生成(`assets/tilesets/tileset.json`,含 `collides` 属性)。 统一结构:`ground` / `obstacles`(`collides=true`)/ `objects`(`spawn`、NPC 点位、`door`、交互点)。 | 场景 | 尺寸(瓦片) | 要点 | |---|---|---| | 小满小屋(室内) | 12×8 | 床、床头日历(C1) | | 村广场 | 30×20 | 公告板、花坛、双子鸟树、庆典场地;枢纽 | | 面包房(室内) | 15×10 | 柜台、烤炉、配方纸(C2) | | 杂货店(室内) | 15×10 | 货架(C5) | | 诊所(室内) | 12×8 | 芙医生、桌上表格(C8) | | 湖畔 | 24×16 | 长椅(龟爷爷)、野餐布、湖面倒影 | | 花田 | 20×14 | 莓果丛(T6)、浇花点 | | 古井空地 | 14×10 | 古井(C7) | | 雾墙边界 | 20×8 | 村庄尽头的雾,E3 入口 | | 白色层 | 20×14 | 走廊 + 病房,去饱和白灰色板 | 重新生成地图(需本机 Tiled,路径 `/Applications/Tiled.app/Contents/MacOS/tiled`): ```bash node tools/gen_tileset_json.cjs node tools/gen_maps.cjs # 可选:用 Tiled 验证导出 "/Applications/Tiled.app/Contents/MacOS/tiled" --export-map assets/maps/plaza.json /tmp/plaza_verify.json ``` ## 目录结构 ``` . ├── index.html ├── package.json ├── tsconfig.json ├── vite.config.ts ├── assets/ │ ├── maps/ # 10 个 Tiled JSON 地图 │ ├── tilesets/ # tileset.png + tileset.json │ └── sprites/ # player.png / npc.png / portraits.png ├── tools/ # Aseprite Lua + Node 生成脚本 └── src/ ├── main.ts # Phaser 配置入口 ├── data/ # gamedata.ts(全部写死的台词/数值/表格)、mapsMeta.ts ├── systems/ # CorruptionDirector / AudioEngine / TextCorruptor / StoryDirector ├── entities/ # Player └── scenes/ # BootScene / TitleScene / UIScene / MapScene / 10 地图 / EndingScene / DebugScene ```