《迷途之梦》v0.1 熟悉笔记 · 为后续章节开发做准备
写于实际通关一轮 + 通读全部源码之后。目的:把「现在有什么、东西都在哪、下一章要动哪里」一次说清楚。 引擎:Godot 4.5 stable(Forward+),源码目录lost-dream/,可执行版E:\godotgame\迷途之梦-未成品\迷途之梦.exe。
一、这是什么游戏
- 改编自同名小说(《有兽焉》同人)。主角是被清除了记忆的狐狸「慕容雪川(美美)」,在梦里被「梼杌」当成死士训练;故事从他发现自己少了一段记忆开始。
- 现版本是战斗验证用垂直切片 v0.1,流程约 10–18 分钟:
标题 → 现实层序章(卧室/失眠/吃药)→ 入梦白幕 → 教学关「热身」→ 第一章「鹿人店的一天」(三波训练)→ 记忆碎片(解锁重击)→ Boss「假面」→ 结束卡 → 回标题。
- 文案/剧本目前是按行号占位的(
文案-待修改.txt、剧本-v1-待填.txt),剧情节点只搭了骨架。 - 完整版规划:五章 + 三结局(斩梼杌 / 杀出天庭 / 不选),见
操作说明.txt末尾。
二、我实际玩到的内容(验证记录)
用窗口注入按键 + 游戏内置 --shots 逐帧截图的方式完整跑了一遍(挑出来的截图在 play/run/keep/):
| 阶段 | 看到的东西 | 结论 |
|---|---|---|
| 标题 | 月亮、屋脊剪影、逐字浮现的「迷途之梦」、狐狸立绘、版本号 | 正常 |
| 序章 | 房间/窗/床/床头桌;日期卡「十月22日」数字乱码滚动;「E 吃下药片」;时间倒流到 7/1;白天/黑夜切换;逐字台词 | 正常,日期动画和关键词高亮(「美美」)都在 |
| 入梦对话 | 13 句空镜头对话(画面无角色),说完才「恍惚」一下把美美浮现 | 正常 |
| 教学关 | 练习一~五;木桩会举刀、有红色弧线预警;短按跳=矮跳 | 五步都能真的判定到(我跑到过「练习五」),但二段跳这一步容易卡住(见问题 4) |
| 三波训练 | 影卒(近战突刺)/ 浮瞳(悬空弹幕)/ 奔角(蓄力冲锋+红色预警线) | 正常,波次标题和提示会覆盖显示 |
| 记忆碎片 | 紫白光柱+菱形,靠近即拾取,解锁「重击」并弹提示 | 正常 |
| Boss 假面 | 登场大字、底部血条、半血进二阶段(红眼+「二阶段」标签)、横扫/跃击地震/三连突进/扇形弹幕 | 正常 |
| 破梦 | 白幕聚光、只有角色是彩色、红色「破!梦!」大字、慢动作 | 正常,效果很成立 |
| 死亡 | 水面浮起(扭曲+去饱和)→ 床头桌/倒药瓶/散落药片一闪 → 沉回;右下角「第 N 次」 | 正常 |
| 击败 Boss | 慢动作 → 白圈收拢 → 全屏白 → 渐灰 → 渐黑 → 结束卡 | 正常 |
| 结束卡 | 「梦到这里就断了。」「——垂直切片 · 完 ——」 | 正常 |
用 --bot 自动操作完整打通了一轮(含死亡、二阶段、破梦、尾声),说明战斗链路是通的。
三、系统与数值(改数值先看这里)
操作
A/D 移动、空格 跳跃(空中再按=二段跳,短按矮跳)、J 轻击三段、K 重击、Shift/L 翻滚(空中=冲刺)、E 拔剑/互动、Esc 暂停、U 历史对话、Q 暂停菜单回标题。 输入映射在 autoload/game_state.gd:80-95(_setup_input),手柄也接了一部分。
玩家(actors/player.gd)
| 项 | 值 | 位置 |
|---|---|---|
| 血量 | 5 | game_state.gd:9 |
| 移速 / 加速度 | 430 / 3600 | player.gd:17-18 |
| 跳跃初速 / 重力 | −930 / 2500 | player.gd:22,25 |
| 翻滚 | 0.34s,无敌帧 0.05–0.26s,速度 660 | player.gd:27-29 |
| 三段轻击 | 1 / 1 / 2 伤,后摇可取消 | player.gd:37-41 |
| 重击 | 3 伤、245px 前向、眩晕 1s | player.gd:44 |
| 破梦 | 5 伤、360×260、全程无敌 | player.gd:42 |
| 斩惑 | 6 伤、绕身 400 宽、0.3s 硬后摇 | player.gd:47-49 |
| 完美闪避 | 翻滚无敌帧内被命中 → 0.32 倍慢动作,2.5s 出手窗口 | player.gd:505-543 |
| 大招冷却 | 破梦/斩惑共用 10s | player.gd:354,368 |
敌人(actors/)
| 敌人 | HP | 行为 |
|---|---|---|
影卒 shadow_soldier.gd | 3 | 走近 96px → 举刀 0.42s → 突刺 470 |
浮瞳 eye_floater.gd | 2 | 保持 330px,悬浮,蓄力 0.5s 后单发弹幕 |
奔角 charger.gd | 4 | 520px 内蓄力 0.7s → 900 速冲锋,撞墙硬直 |
木桩 practice_dummy.gd | 9999 | 只挥刀不掉血,教学用 |
假面 mask_boss.gd | 26 | 二阶段:半血(13)追加扇形 5 连弹;横扫/跃击地震/2–3 连突进 |
波次(scenes/arena.gd:12-28)
1. 影卒×2 2. 影卒×3 + 浮瞳×1 3. 奔角×2 + 浮瞳×1 + 影卒×1 → 记忆碎片 → Boss
存档(autoload/game_state.gd:182-293)
4 个槽 save1.json~save4.json,写在 exe 同级目录;字段:version/hp/shards/deaths/heavy/wave/time/stamp/chapter/progress。 老 save.json 会迁移到第 1 格。读档只从暂停菜单进(标题页没有「继续游戏」)。
UI
全部 draw_* 手绘:HUD(ui/hud.gd)血/碎片/连击/波次大字/提示/Boss 血条/破梦斩惑冷却/死亡计数;暂停菜单 ui/pause_layer.gd;存档面板 ui/save_panel.gd;历史对话 autoload/history.gd。
四、代码架构地图
autoload/ GameState 全局状态 + 输入映射 + 字体 + 存档 + 日志
History U 键历史对话面板
Sfx 全程序化音效(20 路播放池 + 3 个外部 mp3 切段)
Feel 顿帧 / 屏震 trauma / 慢动作(真实时间计时)
Router 全屏淡入淡出
actors/ player 玩家状态机(IDLE/RUN/JUMP/FALL/ROLL/ATTACK/HURT/DEAD)
sprite_rig 位图主角(靠缩放/倾斜/旋转做动作;剑单独画)
fox_rig 程序化狐狸(备用,当前未用)
enemy 敌人基类(重力/受击/眩晕/死亡/镜头夹取)
shadow_soldier / eye_floater / charger / mask_boss / practice_dummy / projectile
fx/ slash_arc(刀光) hit_spark(粒子) after_image(残影) flash_light(闪白)
break_text(破/梦 艺术字) memory_shard(碎片) death_interlude(死亡床头桌) tex_fx
scenes/ main 总流程与场景切换(标题/序章/教学/关卡/结束卡)
title 标题
prologue 现实层脚本剧(date/line/eat/rewind/day/night/forward/end)
arena 第一章关卡(波次、碎片、Boss、死亡重入、暂停、存档接线)
arena_bg 鹿人店背景(有图用图,没图程序化夜景)
tutorial_flow 教学五步状态机
dialogue 过场对话打字机
end_card 结束卡
bot_driver 自动操作(--bot)
ui/ hud / pause_layer / save_panel
tools/ key_out(抠图) sfx_probe sfx_test(音效试听)
数据流:main.gd 用 TitleScreen/Prologue/Arena/EndCard 这些「用代码 new 出来的 Node2D」切换屏幕(main.tscn 只有一个节点)。 Arena 负责一切:建世界/玩家/后处理/HUD/暂停/存档面板,然后按 WAVES 推进。 关卡结束靠信号 finished 往上传;死亡在 Arena 内部循环,不经过 main。
五、下一章要动的地方(按改动量从小到大)
1) 加一段剧情 / 改台词(不用碰逻辑)
- 序章:直接改
scenes/prologue.gd:7-40的SCRIPT数组(date/line/eat/day/night/rewind/forward/end)。 - 入梦对话:
scenes/arena.gd:32-46的INTRO_LINES。 - 波次标题/提示:
arena.gd:12-28的WAVES。 - 教学五步文案:
scenes/tutorial_flow.gd:8-22。 - 结束卡:
scenes/end_card.gd:8-15。 - 其它 UI 大字/提示散布在
arena.gd的hud.announce/prompt调用里。
2) 加一波怪 / 换怪物组合
WAVES 里加一项;_spawn_enemy()(arena.gd:405)加一个 kind 分支即可。位置 x 直接用世界坐标(地面 y=780)。
3) 加一个新敌人
继承 Enemy,实现 _think(delta)、_draw_body()、accent_color()、必要时 _contact_hit_active(); 在 _spawn_enemy 注册;HP/radius/body_top 在 _ready 里设。 注意 Enemy._keep_in_view() 会把怪夹在镜头里,别让它跑到屏幕外。
4) 加一个新 Boss
照 mask_boss.gd 抄:extends Enemy,自己写 _think 状态机 + take_hit 覆盖(Boss 不吃击退)。 注意 HUD 的 Boss 名字是写死的(ui/hud.gd:130「假 面」),多 Boss 必须参数化。
5) 加一整章(重点)
章节系统已经落地了(2026-10-24):
- 章节数据:
scenes/chapters.gd的Chapters.DATA,一条 = 一章:
{id, title, save_label, bg, intro, waves, fragment_after, boss}。 Arena.chapter 决定读哪一条;波次、入梦对话、背景图、碎片位置全从数据里取,arena.gd 里已经没有硬编码的 WAVES。
- 流程路由:
main.gd的_goto_arena(chapter, wave, from_dream, at_boss);第一章打完 Boss →ChapterEnd过场(梦醒 / 黑屏对话 / 「第一章 · 完」)→_goto_arena(2);第二章打完 → 结束卡。 - 存档:
save_slot写chapter_id/chapter/boss,apply_save恢复chapter_id;暂停菜单读档时如果章节不同,Arena发chapter_requested信号,main切到对应章节(_swap会顺手解除暂停)。 - 加新章的步骤:在
Chapters.DATA里加一条 → 在main.gd里决定它接在哪个finished后面(或加一个--state=调试入口)→ 需要独立过场就照chapter_end.gd再写一个。 - 还没做的:标题页「继续游戏」(现在只能从暂停菜单读档)、章节选择界面、每章独立的结束卡文案。
6) 场景/美术
背景只有一张 assets/bg/lurenshop.webp(474×296 放大到 1920,arena_bg.gd 按图片 86% 处对齐地面线 y=780)。 换章=换图;缺图会自动退回程序化夜景。前景草、地面纹理都是代码画的,可以直接复用。 Boss/小怪全是程序化绘制,没有贴图,加新怪不用美术资源。
7) 音频
三个外部采样 assets/sfx/{swing,draw,hit_enemy}.mp3,切段参数在 autoload/sfx.gd:9-18 的 SAMPLE_CUTS。 其余音效(跳/落/翻滚/受伤/心跳/低吼/冲击波/UI…)都是启动时数学合成的,加新音效在 _build_bank() 里加一条。
六、试玩中发现的问题(建议在写新章节前顺手修)
【高】Boss 战里死亡,会重打上一波而不是 Boss —— 已修复(见第九节)
- 现象:Boss 打到约 40% 血时被击杀,画面回到「训 练 · 三」,场上刷出两个奔角;底部 Boss 血条停在死亡时的 40% 不动,之后清完这波又会重新刷一个满血 Boss。
- 定位:
arena.gd:780_redream()先把_entities里所有Enemy(含 Boss)queue_free(),等它跑到:819判断is_instance_valid(_boss)时 Boss 已经被释放 → 走_start_wave(_wave)分支;同时_boss没被置空、hud.set_boss(-1.0)也没执行,所以血条残留。 - 修法:死亡时先判断
_boss(在清理之前),或把「本波是 Boss」单独记一个字段(例如_in_boss),在_redream里据此重刷 Boss,并统一_boss = null+hud.set_boss(-1.0)。
【中】死亡时正在播的波次/Boss 协程没有被作废 —— 已修复(见第九节)
_redream() 不递增 _run_token(只有 _restart_level 会),而 _start_wave / _spawn_boss / _on_fragment_picked 里都有 await(1.0s / 1.6s / 3.4s)。在 await 窗口里死掉,旧协程醒来还会继续刷怪,可能和重开后的内容叠在一起。
- 修法:
_redream()开头_run_token += 1,并在这些协程里像_start_wave那样检查令牌。
【中】可走范围比镜头宽,角色会贴到屏幕边缘被切 —— 已修复(见第九节)
- 玩家 x 被夹在 26–1894(
player.gd:197),但相机limit_left=0 / limit_right=1920、zoom 1.25(可见宽 1536),相机中心只能落在 768–1152。 - 结果:走到 x>1536 或 x<384 的区域,角色会贴边甚至被裁掉(教学关里把角色往右走到头就能看到)。
- 对后续章节的要求:把战斗安排在 x≈384–1536 内,或者把场地加宽/改相机限位。
【低】教学关「二段跳」容易卡住 —— 已改善:提示里写明「长按跳得更高」
- 短按空格=矮跳(
JUMP_CUT 0.42),空中停留只有 ~0.25s;玩家如果按晚了,第二下变成地面起跳,这一步就一直过不去(提示每 13 秒重弹一次,但没有跳过机制)。 - 另外
_enter(1)会把之前做过的二段跳清掉,必须「当下」再做一次。 - 建议:给教学加一个「连续失败 N 次就允许跳过」,或者二段跳判定放宽到「离地后 0.6s 内」。
【低】完美闪避后立刻按 J 可能被吃掉
完美闪避判定的瞬间玩家还在翻滚(翻滚 0.34s),而攻击输入缓冲只有 0.16s(player.gd:147)。如果完美闪避发生在翻滚前段,玩家本能地马上按 J,缓冲会在翻滚结束前过期 → 看起来「按了没反应」,要再按一次才出破梦。
- 建议:把
_buffer_attack调到 0.24–0.3s,或在完美闪避时直接把缓冲补满。
【低】其它
GameState._process是PROCESS_MODE_ALWAYS,暂停时run_time还在涨 → 存档里的「游玩时长」包含暂停时间。- 存档写在 exe 同级目录;如果游戏装在
Program Files,会写不进去(只会提示「存档失败:目录不可写」)。后续上架建议改到user://。 - HUD 的 Boss 名字、二阶段标签、结束卡文字都是写死的,多 Boss/多结局前要参数化。
- 字体
msyh.ttc(19.7MB) +simhei.ttf(9.7MB) 占了 pck 的大头(pck 23MB),正式版建议子集化。
七、给下一章的建议路线
1. 先做工程改造(半天量级):章节数据化 + 存档记录 chapter + 标题页继续 + 修 Boss 死亡重开 + 死亡令牌。这些不碰剧情,但后面每章都会受益。 2. 再做一块「可玩的第二章」:新背景图 → 新 WAVES(建议 2 波小怪 + 1 个精英)→ 新 Boss(换个招式表即可,程序化绘制)→ 关卡入口接到 main。 3. 最后补叙事:把 剧本-v1-待填.txt 里的新场景按「新增场景申请表」填好,我按编号接进 Dialogue/Prologue 那套演出。 4. 分支/结局:GameState.flags 已经是现成的字典,可以用 flags["choice_xxx"] 记选择,结尾按 flags 走不同 EndCard。
八、需要你拍板的问题
1. 第二章的场景是哪里?(鹿人店之后:梼杌的洞府 / 天庭 / 回忆里的某个地方?)要不要新背景图,还是先用鹿人店那张改色? 2. 第二章的玩法想加什么?纯战斗推进 / 加平台跳跃段 / 加潜行或追逐 / 加回忆插叙(可操作演出)? 3. 剧情节点先写还是先搭关?按你 剧本-v1 的节奏,我可以先把「第二章 · 场景 S-1」的空壳搭出来给你试玩。 4. 是否允许我改 arena.gd 的结构(章节数据化)?这会动到现有第一章的代码,但会保留现有手感和文案。
九、这一轮修掉的 bug(2026-10-24)
改动文件:scenes/arena.gd、actors/player.gd、scenes/tutorial_flow.gd、autoload/game_state.gd(攻略文案)、README.md、操作说明.txt、剧本-v1-待填.txt、文案-待修改.txt。
1. Boss 战死亡 → 满血重开 Boss(问题 1)
Arena新增_boss_active:Boss 登场或在场时为 true,清场/重开时复位。_redream()在清理战场前先记下「死前是不是在 Boss 段」,清怪后_boss = null+hud.set_boss(-1.0),再按记录重新_spawn_boss()(满血、一阶段)。- 不再出现「死在 Boss 手里 → 回到训练三」和「血条停在 40%」。
- 验证:站着不动被 Boss 打死,画面重新播「假 面」登场、血条满格(
play/run/keep/13_boss_restart_full_hp.png);--bot仍能打到结束卡。
2. 死亡重入的协程竞态(问题 2)
_redream()现在也_run_token += 1,每个 await 后校验令牌,失效就退出;_check_clear()里 0.7s 的 await 也补了令牌校验。- 效果:死在波次提示 / Boss 登场 / 碎片演出的 await 窗口里,旧协程醒来直接作废,不会和重开后的怪叠在一起。
3. 角色被镜头切边(问题 3)
Player新增bounds_min / bounds_max(默认仍是老的 26 / 1894,老关卡不受影响);Arena._build_player()设为 90–1830:镜头可见宽 1536、相机中心只能落在 768–1152,两端各留 90px,角色整个人都在画面里。- 验证:一直往右走,角色停在 x=1830、屏幕 94% 处,不再被裁(
play/run/keep/14_player_bound_1830.png)。
4. 教学关介绍「长按跳更高」(你的第 4 点)
- 练习一:「空格 跳起来(长按 = 跳得更高,短按 = 矮跳)」
- 练习二:「先长按空格跳高,在空中再按一次 空格 = 二段跳」
README.md、操作说明.txt、剧本-v1-待填.txt的现文案、文案-待修改.txt的现文案、暂停菜单「查看攻略」里的操作说明都同步了。
2026-10-24 第二轮:章节系统 + 第一章完过场 + 历史对话
5. 章节概念
- 新增
scenes/chapters.gd(Chapters.DATA)与Arena.chapter;波次 / 入梦对话 / 背景图 / 碎片位置全部数据化。 main.gd改为_goto_arena(chapter, …);第一章结束 →ChapterEnd→ 第二章;第二章结束 → 结束卡。- 存档多写
chapter_id/boss;跨章读档由chapter_requested信号交给main切章。 - 调试入口:
--state=arena2直接进第二章。
6. 第一章完 · 梦醒过场(scenes/chapter_end.gd,台词来自 加对话.txt)
- 白 → 白天房间(
scenes/room_bg.gd,从序章抽出来的共用卧室背景)→ 美美 4 句 + 窗外音效提示; - 压黑 → 核桃那段对话(含「………………」停顿);
- 「第 一 章 · 完」大字 → 进第二章(空壳:直接再打一次假面,打完通关)。
- 验证:
--state=boss --bot全流程跑通,截图见play/run/keep/16_chapter_end_wake.png(梦醒)、17_chapter_end_black.png(黑屏对话)、18_chapter1_end_card.png(第一章完)、19_chapter2_boss.png(第二章假面)。
7. U 键历史对话
- 对话框出现时右下角常驻「U 查看历史对话」(
dialogue.gd、prologue.gd)。 - 修了一个漏记:过场对话(Dialogue)之前完全没进历史,现在每句都会
GameState.add_log;历史面板显示条数从 14 条提到 24 条。 - 验证:序章按 U 能看到日期卡和台词(
play/run/keep/20_history_panel.png)。
8. 说话人名字颜色 + 标题卡死修复
Dialogue支持每句"color":美美浅橙、???/核桃白、凶的???深红;序章名字色统一。- 修:标题淡入的 1 秒里按键会把
TitleScreen._done提前置位,导致之后按键再也叫不醒标题。现在main先接pressed再淡入,TitleScreen也会在没人接信号时忽略按键。
重新打包的迷途之梦.pck放在play/build/(和你的 exe 同一版本导出),替换E:\godotgame\迷途之梦-未成品\迷途之梦.pck即可,exe 不用动。
*附:可直接运行的调试参数* -- --state=title|prologue|tutorial|arena|arena2|fragment|boss、--bot、--god、--tutskip、--shot=<绝对路径> --delay=秒、--shots=<前缀> --count=N --interval=秒、--slow、--sfxtest、--spottest、--savetest[=load]、--pausetest。 源码运行:E:\godot\Godot_v4.5-stable_win64.exe --path <lost-dream 目录>。