6.5 KiB
6.5 KiB
崩坏童话:蜜糖村(网页版)
纯单机网页游戏 · Phaser 3 + TypeScript + Vite · 无后端、无存档、无 localStorage,浏览器打开即玩。
一个看起来百分之百治愈的像素童话村庄,实际是一场情绪疗程的沉浸幻境。玩家越"幸福",世界越饱和、越甜、越不对劲;通往真相的路,恰恰是那些系统禁止的悲伤。
启动方式
需要 Node.js 18+。
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):
"/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):
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