《迷途之梦》怪物长文解析(小怪 6 种 · Boss 2 个)
数据全部来自源码逐行核对,不是凭手感估的。时间单位是游戏时间(物理 120 帧/秒,1 帧 ≈ 8.3ms), 顿帧/慢动作会拉长真实时间,文中会单独标。 所有引用行号对应当前源码(actors/*.gd、scenes/arena.gd)。 实机截图见playtest-通关实录/。
0. 一页结论
| 敌人 | HP | 一句话定位 | 关键机制 | 威胁 | 设计完成度 |
|---|---|---|---|---|---|
| 影卒 | 3 | 近战标准答案 | 0.42s 举刀 + 红箭头 | ★★☆ | ★★★★ |
| 浮瞳 | 2 | 强制你跳起来 | 悬空 330px 放直线弹 | ★★★ | ★★★☆ |
| 奔角 | 4 | 教你"别站原地" | 0.7s 蓄力 + 900 速冲锋 | ★★★ | ★★★★ |
| 野猪 | 7 | 奔角的血量变体 | 同奔角,血厚 75% | ★★★★ | ★★☆ |
| 藤蔓 | 3 | 距离管理 + 弹幕(改版后) | 抽打 0.55s(可跑开)/ 绿色种子(可滚可跳)/ 缠绕 3s | ★★★☆ | ★★★☆ |
| 木桩 | ∞ | 教学陪练 | 0 伤害 | — | ★★★★ |
| 假面 | 26 | 第一章的"考卷" | 横扫单帧判定 + 二阶段 | ★★★★ | ★★★★ |
| 丛林石像 | 33 | 两段式 Boss | 落石 + 砸地 → 掉头(身体 10 + 飞头 7) | ★★★★ | ★★★☆ |
五条判断:
1. 小怪的设计语言是统一的、可读的——四个字:接近、预警、单次判定、走。 2. 但"单次判定"这个共性,让翻滚无敌帧变成了万能解:只要滚对时机,所有怪都一样。 3. 藤蔓曾经是 bug 级的例外(2026-10-27 已修):改版前它"锁定必中 + 减速穿透无敌帧 + 6 秒禁翻滚";现在改成"抽打可跑开 / 绿色种子可滚可跳 / 缠绕 3 秒且仍能翻滚"。 4. 假面是设计得最好的怪:单帧横扫(反直觉但可学)、二阶段白给窗口、重击可打断,有"读招"的乐趣。 5. 丛林石像从"最差"变成了"唯一有两段式"的 Boss(2026-10-27):血量掉到 17 时头掉下来,身体 10 血 + 飞头 7 血同时在场;砸地也补上了红色落点预警。
1. 敌人系统的七条"语法"
在逐个分析之前,先讲清楚这套系统里所有怪共用的规则——理解这七条,就理解了为什么打起来是那个感觉。
1.1 所有攻击都是"三段式":接近 → 预警 → 单次判定
idle → approach/telegraph → attack(判定 1 次) → recover → idle
↑
红色预警(0.4–0.9s)
没有一个敌人有多段判定、持续判定或二段变招。 推论:翻滚的无敌窗口(0.21s)只要覆盖住那一下,就永远安全。这是"一招通吃"的根。
1.2 状态机骨架是共享的(enemy.gd)
| 状态 | 谁在用 | 含义 |
|---|---|---|
spawn | 全部 | 0.55s 入场,不思考、不判定 |
idle | 全部 | 站定,等冷却/等距离 |
approach / chase | 影卒 / 奔角 / 浮瞳 | 走位 |
telegraph | 影卒 / 奔角 / 浮瞳 / 木桩 / 藤蔓 | 预警 |
lunge / dash / swing / lash / sweep / slam / fan / rocks / fist | 各自 | 出手 |
recover | 影卒 / 奔角 / 浮瞳 / 木桩 | 收招(破绽窗口) |
"recover 才是输出窗口" 这个节奏是全游戏共用的,玩家学会一次就通用。
1.3 接触伤害有"白名单"
基类只在 _contact_hit_active() 返回 true 时才判定贴身伤害(enemy.gd:78–82):
if _contact_hit_active() and tdx < radius * scale.x + 16.0 and tdy < 62.0 and not is_in_group("boss"):
_touch_damage(1, 240.0)
| 敌人 | 什么时候有接触伤害 |
|---|---|
| 影卒 | 只在 lunge(突刺那 0.16s) |
| 奔角 / 野猪 | 只在 dash(冲锋中) |
| 浮瞳 | 从不(只有弹幕) |
| 木桩 | 只在 swing(且伤害 0) |
| 藤蔓 | 不走这条规则:自己在出手瞬间判距离(见 2.5) |
| Boss | 基类直接跳过(not is_in_group("boss")) |
意义:除了出手的那几帧,贴身是安全的 → 所以"贴脸砍"是正确打法,游戏并不惩罚你站得近。 细节:纵向判定写死 < 62,不随体型缩放,所以跳起来(173px)能躲掉所有地面接触伤害。
1.4 预警的颜色语言
| 颜色 | 含义 | 谁在用 |
|---|---|---|
红 #ff4a4a 系 | "马上要打到你" | 影卒箭头、奔角虚线、浮瞳瞄准线、木桩弧、假面横扫弧、落石圈 |
橙 #e08a3a | 身份色 | 奔角、野猪 |
紫 #7d4fd0 / #a071ff | 身份色 | 影卒、浮瞳 |
粉 #d05fa0 | Boss 身份色 | 假面 |
灰 #5b554d | Boss 身份色 | 石像 |
统一的红色预警是这套系统最值得夸的地方:玩家不需要记每个怪的动作,只需要记"红色 = 现在该滚"。
1.5 受击反馈
- 命中:
flash = 1.0(白闪)+ 火星 +_hurt_stun = 0.22s(停止思考、急速减速) - 血条:只在
0 < hp < max_hp时画,宽 40px,位于body_top − 14 - 眩晕(重击):头顶 3 颗小星星绕圈 + 一圈弧
- 死亡:爆散 +
defeated信号 → 由 Arena 处理"这一波清完没"
数值细节:任何命中都会给 0.22s 硬直,而重击额外给 1.0s 眩晕(Boss 只有 0.35s)。 0.22 + 1.0 = 小怪被打中就基本失去行动能力 → 重击是小怪的"无限控"(这也是设计问题,后面说)。
1.6 镜头夹取:你跑不掉
Enemy._keep_in_view() 每帧把怪夹在镜头可见范围 ±44px 内:
var lo := center.x - half.x + 44.0
var hi := center.x + half.x - 44.0
推论: 1. 风筝战术无效——你往后退,怪会贴着屏幕边缘跟过来,永远不会掉出画面。 2. 场地两端的 384px 死区(相机限位造成)是"怪堆叠区":往后躲,怪会全挤在屏幕边上。 3. Boss 也吃这条规则,所以它不会被你拖出画面。
这是个好设计:它把"跑"这个选项的成本提高了,逼你正面对抗。副作用是"站在屏幕边缘"有时能卡住怪的寻路(它们会贴边滑)。
1.7 绘制:两个函数定身份
所有角色都是代码画的,靠两个函数区分:
func body_color() -> Color # 身体色
func accent_color() -> Color # 描边光晕色
func _draw_ghost(c, w, p) # 光晕("影子")
func _draw_body(col, pulse) # 本体
所以"加一个新怪"= 写一个 _think() + 一个 _draw_body(),没有美术依赖。这是这套代码最实用的地方。
2. 小怪逐一解剖
2.1 影卒(shadow_soldier.gd,132 行)
定位:近战的标准答案。它是你遇到的第一个怪,也是唯一一个只考"时机"的怪。
数值卡
| 项 | 值 | 行 |
|---|---|---|
| HP | 3 | 13 |
| 体型 | 1.45× | 17 |
| 碰撞半径 | 22(判定 = 22×1.45+16 ≈ 48px) | 14 |
| 移速 | 132 | 4 |
| 攻击距离 | 96(进入这个距离才举刀) | 5 |
| 接触伤害 | 1,仅 lunge 时 | 62 |
时序
| 状态 | 时长 | 累计 | 说明 |
|---|---|---|---|
| idle | 0.25 | 0.25 | 站定 |
| approach | 直到 <96px | — | 132 速走过来 |
| telegraph | 0.42 | — | 举刀 + 地面红色箭头逐帧变长 |
| lunge | 0.16 | 0.58 | 470 速前刺(约 75px),这一帧起有接触伤害 |
| recover | 0.55 | 1.13 | 收招,唯一的安全输出窗口 |
| 冷却 | 0.7–1.4 | — | 再接近 |
判定细节
- 接触判定是在
lunge期间每帧检查tdx < 48 && tdy < 62,所以其实有 0.16s 的判定窗口(不是单帧)。 - 突刺只有 75px,所以"举刀时后退一步"就能让它刺空。
- 纵向 62 < 跳高 173 → 跳过去也安全。
画法:锥形袍 + 圆头 + 面具(一条紫色横线 + 一个亮点)+ 一把刀,刀的角度随状态插值(0.9 → −1.5 → 0.35)。 预警是"从身上射出一条红色箭头,随 state_t/0.42 变长"——这是全游戏最清楚的预警。
对策 1. 看到举刀 → 朝它滚过去(吃完美闪避)或后退一步。 2. 收招 0.55s 是输出窗口,正好够三段轻击的前两段。 3. 三个一起出现时,它们的前摇是错开的 → 逐个滚、逐个收。
评价
- 优点:教科书级的"可读性"。0.42s 前摇 + 红色箭头 + 固定 96px 触发距离,玩家第一次见就能学会。
- 问题:它太"标准"了——0.42s 前摇在所有怪里是最长的,导致它成为最好滚的怪,几乎没有威胁。它是教学怪,不是战斗怪。
2.2 浮瞳(eye_floater.gd,125 行)
定位:强制你离开地面的怪。它是唯一一个"站在地上打不到"的敌人。
数值卡
| 项 | 值 | 行 |
|---|---|---|
| HP | 2 | 14 |
| 体型 | 1.4× | 20 |
| 碰撞半径 | 24(但它没有接触伤害) | 15 |
| 重力 | 0(悬空) | 15 |
| 悬浮高度 | 出生点上方 120 → y ≈ 656(离地 124px) | 21 |
| 保持距离 | 330 | 5 |
| 移速 | 横向上限 190,纵向上限 140 | 39–41 |
| 弹速 / 伤害 | 460 / 1(弹丸半径 10,命中距离 32) | 76 |
时序
| 状态 | 时长 | 说明 |
|---|---|---|
| idle | 0.4 | 入场后先站一下 |
| chase | 直到 _fire_cd 归零(首次 0.6–1.6,之后 1.5–2.4) | 维持 330 距离、上下浮动 ±26 |
| telegraph | 0.5 | 停住、眼睛放大发光、画红色瞄准线 |
| fire | 瞬间 | 朝玩家(player + (0,−50))打一发 460 速弹 |
| recover | 0.85 | 不还手 |
判定细节
- 没有接触伤害(
_contact_hit_active()继承默认 false)→ 贴它脸也不会被打。 collision_mask = 0→ 不撞地形,穿墙悬浮。- 弹丸是手工距离判定:
distance_to(player + (0,−50)) < radius + 22 = 32px。 - 它离你 330px,而你的攻击距离只有 124px → 你必须跳/冲刺过去,或者等它靠近。
- 它的纵向判定:站在地面打不到(它在 656,你在 776);但空中砸地(半径 130)能打到,因为冲击波圆心在 734,距离 656 只有 78。
设计意图(很聪明):
它逼玩家做一件平时不会做的事——主动起跳。而跳跃/空中冲刺/空中砸地正好是教学关教过的东西。 同时它给了"跳跃"一个进攻理由(而不是只有躲),这是很高级的引导。
画法:菱形外壳 + 5 根触须 + 一只眼球(会随 sin 移动瞳孔),蓄力时眼睛放大 1.5 倍 + 红色瞄准线。
对策 1. 跳跃 + 空中 J(砸地)一次能秒它(2 HP)。 2. 或者用破梦(360×260 的大判定框能打到空中)。 3. 别在地面上和它耗——它会一直保持 330 距离放风筝。
评价
- 优点:唯一改变了"平面战斗"的怪;用"打不到"逼出跳跃,是很好的机制教学。
- 问题:只有一个。它本该是一个"种类"(对空弹幕、追踪弹、延迟爆炸),现在只是一个怪。
- 小瑕疵:被连续命中时
_hurt_stun会打断悬浮逻辑,但它有速度残留 → 会被打得横向漂移。
2.3 奔角(charger.gd,127 行)
定位:教你"别站原地"的怪。它是第一个有位移型攻击的敌人。
数值卡
| 项 | 值 | 行 |
|---|---|---|
| HP | 4 | 12 |
| 体型 | 1.5× | 16 |
| 碰撞半径 | 28(冲锋判定 = 28×1.5+16 ≈ 58px) | 13 |
| 常速 / 冲锋 | 70 / 900 | 4–5 |
| 触发距离 | 520(很大) | 32 |
| 接触伤害 | 1,仅 dash 时,纵向 <56(可以被跳过) | 49–52 |
时序
| 状态 | 时长 | 说明 |
|---|---|---|
| idle | 0.3 | |
| approach | 直到 <520px 且冷却好 | 70 速慢慢挪 |
| telegraph | 0.7 | 后坐下蹲 + 6 段红色虚线,同时向后退 30 速(起跑距离) |
| dash | ≤1.0 | 900 速冲锋,速度按 clamp(1 − t×0.35, 0.5, 1) 衰减 → 0.7s 内约 520px,跑满 1 秒约 730px |
| 撞墙 | — | 额外震屏 + 火星 + 立刻转 recover |
| recover | 1.0 | 硬直,白给窗口 |
| 冷却 | 1.4–2.2 |
判定细节
- 冲锋判定
tdx < 58 && tdy < 56:纵向只有 56,跳起来(173)完全免疫。
——所以"跳过冲锋"是官方解法,而且它撞墙后还有 1 秒硬直,是白给。
- 冲锋距离远(500–600),但有墙:场地左右墙 x=−30/1950,撞上就硬直。
- 它不会在冲锋中改向(直线),所以站位在它侧后方就是绝对安全。
画法:椭圆躯干 + 背脊鬃 + 独角 + 橙色眼睛;蓄力时下蹲 12px;预警是 6 段向前的红色虚线。
对策 1. 最优:跳过去(它冲锋时纵向判定只有 56)。 2. 次优:横向跑开,让它撞墙 → 1 秒硬直 → 三段轻击(4 伤正好打死)。 3. 别用翻滚硬吃——虽然能躲,但它是"最好用走位解决的怪"。
评价
- 优点:唯一一个"空间解法"优先于"帧解法"的怪。它给了玩家"跑位"这个选项,而不是只有滚。
- 优点:撞墙硬直是对"利用地形"的奖励。
- 问题:冲锋 900 速 + 触发距离 520,在一维战场上意味着它一冲就是半屏,如果玩家在场地中间,它几乎必定冲到对面墙——所以它每次冲锋都在送。
2.4 野猪(boar.gd,18 行)
定位:奔角的血量变体。它只有 18 行代码,因为它 extends Charger,只改了三个值。
func _ready() -> void:
super._ready()
max_hp = 7 # 奔角 4
hp = 7
scale = Vector2(1.7, 1.7) # 奔角 1.5
func body_color() -> Color: return Color("#6b4a2f")
func accent_color() -> Color: return Color("#d9b27a")
数值差异
| 项 | 奔角 | 野猪 | 影响 |
|---|---|---|---|
| HP | 4 | 7 | 一套三段轻击(4 伤)打不死,要 2 套 |
| 体型 | 1.5 | 1.7 | 冲锋判定 58 → 63.6px,视觉更压迫 |
| 速度 / 冲锋 / 时序 | — | 完全相同 | 行为一模一样 |
设计问题(这是丛林关变难的一半原因) 1. 它只是"更肉的奔角",没有新招、没有新解法 → 玩家的策略不变,只是要多打 1.3 秒。 2. 多出来的这 1.3 秒,正好是它下一个冲锋周期的开始 → 第二套连击往往要在它冲锋前摇里打完,风险陡增。 3. 三只野猪同屏时,它们的前摇会错开 → 你每 1.5 秒就要滚一次,几乎没有输出窗口。
一句话:野猪是"用数值拖时间"的怪,不是"用机制加难度"的怪。这在动作游戏里是最廉价、也最容易被玩家察觉的难度手段。
2.5 藤蔓(vine.gd,约 150 行 · 2026-10-27 改版)
定位:唯一考"距离管理 + 弹幕闪避"的复合怪。 改版前它是全游戏唯一的"必中怪"(无距离检查 + 减速穿透无敌帧 + 0.95 秒无冷却 + 减速 6 秒禁翻滚)——丛林关卡 15 连死的根因。现在改成了两个都能躲的招式。
数值卡(新版)
| 项 | 值 | 说明 |
|---|---|---|
| HP | 3 | |
| 体型 | 1.2× | |
| 碰撞半径 | 22 | |
| 移速 | 0(完全不动) | |
| 抽打距离 | 220 | 出手时才判定 |
| 种子射程 | 560 | |
| 攻击节奏 | 2.0 秒(两招共用冷却) | 原来是 0.95 秒且无冷却 |
| 种子 | 330 速 / 半径 10 / 1 伤 | 命中挂「缠绕」 |
| 缠绕时长 | 3 秒 | 原来 6 秒且禁翻滚 |
两个招式
① 种子(新增)
| 阶段 | 时长 | 说明 |
|---|---|---|
| 瞄准 | 0.50 | 花口聚起绿光 + 一条淡绿瞄准线(可读成"有东西要飞过来") |
| 发射 | 瞬间 | VineSeed:绿色种子,330 速,朝玩家胸口飞 |
| 收招 | 0.30 |
- 可以躲:种子是正常投射物,判定
距离 < 半径+22,所以翻滚无敌帧能挡、跳过也能躲(弹道从花口的 −156 飞向胸口 −50,跳起来就擦过去了)。 - 近身也会吐:贴着打时仍有 45% 概率改吐种子(原来是"近身只抽打"),避免"贴脸就看不到新机制"。
② 抽打(保留,但修好了)
| 阶段 | 时长 | 说明 |
|---|---|---|
| 预警 | 0.55 | 红色挥砍弧 |
| 出手 | 一帧 | 出手那一帧才检查距离:< 250 才命中 → 跑出去就能躲 |
| 收招 | 0.32 |
改版前的问题:_touch_damage()基类没有距离检查,藤蔓在进入 lash 的那一帧无条件调用它 → 只要你在它 220px 内待过 0.55 秒,这一下必中;而且apply_vine_slow()是独立语句,完美闪避挡了伤害也照样被减速。现在补了距离检查。
缠绕(改版后)
被打中(种子或抽打)→ 3 秒「缠绕」:
| 影响 | 改版前 | 改版后 |
|---|---|---|
| 移速 | ×0.5 | ×0.6 |
| 跳跃初速 | ×0.2(跳高只剩 7px) | ×0.65(跳高约 73px) |
| 翻滚 | 完全禁用 | 仍然可用(0.85 倍速) |
| 时长 | 6 秒 | 3 秒 |
| 表现 | 只有角色闪白 | 身上缠三圈绿藤 + 叶子(fx/vine_bind.gd) |
"翻滚仍然可用"是最关键的一条:原来一旦被缠,唯一的解法(翻滚)被锁死,而丛林同时有 3 只 900 速野猪 → 中了就等死。现在被缠还能翻滚脱身,"缠绕"变成减速而不是瘫痪。

画法
- 绿褐色藤蔓主干(18px)+ 4 片叶子 + 顶部暗红花口。
- 抽打预警:红色弧线(和其他怪一致的红色语言)。
- 种子预警:花口绿光由小变大 + 淡绿瞄准虚线。
- 视觉仍与实际受击体不一致:视觉高约 204px,可被打的胶囊只有底部约 74px(打上半截不掉血)——这点没改。
对策(新版) 1. 中距离:贴着脸反而安全(抽打可以跑开),种子飞过来时滚过去或跳过去。 2. 贴身:3 血 = 一套三段轻击(4 伤)就能秒,在它 0.55 秒预警里打死它是最优解。 3. 被缠了:还能翻滚,先滚出野猪的冲锋线,等 3 秒。
评价
- 优点:从"不讲理"变成"可以读"。现在它真正在考"距离 + 弹幕",而不是考"你有没有提前 6 秒知道要减速"。
- 优点:种子给了一个"绿色 = 可以滚"的新视觉词,补上了原来"所有预警都是红色"的单调。
- 仍存在的瑕疵:受击体比视觉小;抽打的 250px 判定略大于 220 的预警距离(预警弧画在 124 半径,视觉上比实际判定小很多)。
2.6 木桩(practice_dummy.gd,127 行)
定位:教学专用假怪。它的存在意义只有一个:让玩家安全地练习"迎着攻击翻滚"。
数值卡
| 项 | 值 |
|---|---|
| HP | 9999(打不死) |
| 体型 | 1.15× |
| 攻击距离 | 330(很大,站近就会挥) |
| 时序 | 0.9s 举刀 → 0.26s 挥 → 0.8–1.3s 冷却 |
| 伤害 | 0(_touch_damage 被覆写成 hurt(0, dir, 170)) |
巧思:它是全游戏唯一一个"故意打不中还陪着你"的怪。
- 用 9999 血而不是"无敌"标记,实现简单但语义不对(它仍然走完整的受击流程)。
- 0 伤害意味着玩家可以毫无成本地反复练——这是教学关最需要的东西。
- 头顶挂着「木 桩」两个字(用系统字体画),明确告诉你"这是靶子"。
评价:作为教学工具,它是合格的。唯一的遗憾是它只教了"完美闪避"一件事,没有教"重击眩晕""破梦"(这两个后面靠自己摸)。
3. 横向对比与难度当量
3.1 解法矩阵:面对每种攻击,哪些操作有效?
| 敌人攻击 | 翻滚 | 跳跃 | 走位 | 打回去 |
|---|---|---|---|---|
| 影卒突刺 | ✅ | ✅(纵向 62) | ✅(退一步) | ✅(打断前摇) |
| 浮瞳弹幕 | ✅ | ⚠️(看时机) | ✅(横向跑) | ✅ |
| 奔角冲锋 | ✅ | ✅✅(纵向 56,最优) | ⚠️(要看墙) | ⚠️(要卡前摇) |
| 野猪冲锋 | ✅ | ✅✅ | ⚠️ | ⚠️ |
| 藤蔓抽打 | ✅(还能躲减速) | ⚠️(弹道可躲) | ✅(跑出 250px) | ✅ |
| 假面横扫 | ✅ | ✅(纵向 120 太厚,只能到最高点) | ✅✅(站 >380) | ⚠️ |
| 假面突进 | ✅✅(必须) | ⚠️ | ❌ | ❌ |
| 假面弹幕 | ✅ | ⚠️ | ✅ | ✅ |
| 落石 | ✅ | ❌(不看 y) | ✅✅(走位最优) | ❌ |
| 石拳 | ✅ | ⚠️ | ✅✅(>270) | ⚠️ |
一眼就能看出来:除了藤蔓,几乎所有攻击都是"翻滚 / 跳跃 / 走位"三选一。 唯一"只有一种解"的,就是藤蔓——而它恰好是唯一一个必中的。
3.2 波次难度当量(用 HP 算)
| 章节 | 波次 | 组成 | 总 HP | 强制命中源 |
|---|---|---|---|---|
| 第一章 | 1 | 影卒×2 | 6 | 0 |
| 2 | 影卒×3 + 浮瞳 | 11 | 0 | |
| 3 | 奔角×2 + 浮瞳 + 影卒 | 13 | 0 | |
| 4 | 影卒×2 + 浮瞳 + 奔角 | 12 | 0 | |
| 5 | 影卒×3 + 奔角 + 浮瞳 | 15 | 0 | |
| 第二章·梦 | 1–3 | 影卒/浮瞳为主 | 9 / 8 / 13 | 0 |
| 第二章·丛林 | 1 | 野猪 + 藤蔓×2 | 13 | 2 |
| 2 | 野猪×2 + 藤蔓×2 | 20 | 2 | |
| 3 | 野猪×3 + 藤蔓×2 | 27 | 2 |
丛林第三波的 HP 是第一章最难波的 1.8 倍,而且多了 2 个"必中 + 减速"源。 这就是"难度断崖"的量化解释:不是"稍微难一点",是一整套新规则一次性丢给你。
3.3 威胁类型的覆盖(这套设计缺什么)
| 威胁类型 | 有没有 |
|---|---|
| 近战单段 | ✅ 影卒 |
| 远程直线 | ✅ 浮瞳、假面弹幕 |
| 冲锋 / 位移 | ✅ 奔角、野猪 |
| 站桩控制 | ✅ 藤蔓 |
| 地面 AOE | ✅ 落石 |
| 对空 / 空中追击 | ❌ 一个都没有 |
| 多段 / 持续判定 | ❌ 一个都没有 |
| 抓取 / 无视无敌帧 | ❌ 一个都没有 |
| 召唤 / 分裂 | ❌ 一个都没有 |
| 护盾 / 破防 | ❌ 一个都没有 |
| 精英怪(血厚 + 特殊机制) | ❌ 缺这一档 |
结论:这套怪物池能撑起"手感验证",但撑不起"长线战斗设计"。 因为缺了"反翻滚/反跳跃/反重击"这三类,玩家永远只有一套最优解。
4. Boss「假面」深度解析
4.1 数值与体型
| 项 | 值 | 备注 |
|---|---|---|
| HP | 26 | 半血(13)进二阶段 |
| 体型 | 1.55× | 视觉高度约 1.55×150 = 230px |
| 碰撞体 | 胶囊 半径 46 / 高 112,位于 y=−56 | 覆盖躯干+头,不包括刀 |
| 判定半径 | 44 | |
| 移速 | 96 | 很慢,"走"过来 |
| 决策间隔 | 0.8s(初始) | 每次出招后 0.45s(一阶段)/ 0.25s(二阶段) |
| 受击 | 不吃击退(kb × 0.12),_hurt_stun 不生效 | 所以不能靠打退它 |
| 眩晕 | 重击 → 0.35s,并打断当前招式 | 这是打它的关键 |
4.2 四个招式

① 横扫
| 阶段 | 时长 | 说明 |
|---|---|---|
| 举刀 | 0.55 | 手臂从 1.2 抬到 −1.9,画红色弧线预警 |
| 判定 | 单帧 | 只在 _atk_t ≥ 0.55 的那一帧检查一次 |
| 甩刀 | 0.17 | 手臂扫到 0.9 |
| 收招 | 0.6 |
判定几何:圆心 = 自身 + (朝向 × 142.6, −111.6),半径 = 235.6。 玩家判定点在 player + (0,−50),所以要 <235.6 才中。
关键:这是一次性判定。也就是说:
- 站在 380px 外 → 完全安全;
- 站在它背后 → 安全(圆心在身前);
- 甚至可以在 0.55s 之后再走进去,一样安全。
这是全游戏最"反直觉"的设计:看着最吓人的大刀横扫,其实是最好躲的招。
② 跃击地震
| 阶段 | 时长 | 说明 |
|---|---|---|
| 蓄力 | 0.35 | 站定 |
| 起跳 | 0.75 | velocity.y = −760,空中额外重力 2600 |
| 落地 | — | 生成左右两发地面冲击波(投射物:520 速、半径 15、1 伤、寿命 2.2s) |
| 收招 | 0.8 |
注意:落地本体没有判定,只有那两发冲击波有伤害。 安全解:跳过冲击波 / 翻滚 / 站远。危险度最低的一招。
③ 突进(2 连 / 二阶段 3 连)
| 阶段 | 时长 | 说明 |
|---|---|---|
| 蓄力 | 0.32 | 停下来,头周围一圈粉色光(不是红色) |
| 冲刺 | 0.42 × n | 980 速,判定 tdx<120 && tdy<120 → 1 伤 + 420 击退 |
| 连段间隔 | — | 立刻反向 260 速拉回,再蓄 0.32 |
| 收招 | 0.6 |
这是最危险的一招:980 速、纵向 120(跳不过去,只有到最高点 173 才免疫)、还能连 2–3 次。 正确解法只有翻滚(或者站到它冲刺的反方向)。
④ 扇形弹幕(仅二阶段)
| 阶段 | 时长 | 说明 |
|---|---|---|
| 蓄力 | 0.55 | 粉色光晕 |
| 发射 | 瞬间 | 5 发 ±0.4rad、430 速、半径 10 |
| 收招 | 0.5 |
安全解:翻滚 / 横向跑(弹幕是扇形散开的,中间有缝)。
4.3 决策权重(mask_boss.gd:127–159)
var options := ["sweep"] # 横扫永远在池子里
if adx > 220: options += ["dash", "dash"] # 站远 → 突进权重 ×2
if adx < 520: options += ["slam"] # 站近 → 加跃击
if phase == 2: options += ["fan", "sweep"] # 二阶段加弹幕 + 再加一次横扫
| 距离 | 一阶段选项 | 二阶段选项 |
|---|---|---|
| <220 | 横扫 / 跃击 | 横扫×2 / 跃击 / 弹幕 |
| 220–520 | 横扫 / 突进×2 / 跃击 | 横扫×2 / 突进×2 / 跃击 / 弹幕 |
| >520 | 横扫 / 突进×2 | 横扫×2 / 突进×2 / 弹幕 |
设计意图(很好):站远会勾引突进(权重翻倍)。 这直接惩罚了"我站远看清楚再打"的保守打法,逼你进入 220–520 的中距离区间——而这个区间正好是"横扫能打到你、跃击也会来"的危险带。
这是一个真正的"位置博弈",在小怪身上完全没有。
4.4 二阶段
半血(hp ≤ 13)时强制触发:
phase = 2
phase_changed.emit(2)
Feel.shake(0.7); Sfx.play("roar"); FlashLight.flash(...)
_end_attack(0.9) # ← 强制收招 0.9 秒
这 0.9 秒是官方白给窗口:它不打你、不动,站着让你打。 一阶段打到 13 血 → 强制进二阶段 → 白打 0.9s(够一套三段 + 一次重击)→ 二阶段开始。
视觉反馈:眼睛从暗紫变成亮红,HUD 血条从 #d0455c 变成 #ff2f6a,右侧出现「二阶段」小字。
4.5 被打断:重击是它的"解药"
func stun(seconds: float) -> void:
var t := minf(seconds, 0.35)
super.stun(t)
_attack = ""; _jumping = false; _atk_t = 0.0; _clear_flags()
state = "walk"; state_t = 0.0; _decide_cd = 0.35
每一次重击命中 = 取消它当前正在起手的招 + 0.35s 硬直。 所以打假面的循环可以是:贴脸 → 重击打断 → 平A → 重击打断。 这是它设计得最好的一处:给了玩家一个"主动"的工具,而不只是被动躲。
4.6 三层打法(从菜到强)
| 层次 | 打法 | 用到的机制 |
|---|---|---|
| 新手 | 站远,看招,滚开,趁机打两下 | 走位 + 翻滚 |
| 中级 | 在横扫 0.55s 时迎着滚进去 → 完美闪避 → 破梦 | 完美闪避 + 破梦 |
| 高级 | 重击打断起手 → 平A → 二阶段白给窗口打一套 + 重击 → 循环 | 重击 + 阶段窗口(破梦/斩惑仍要先吃完美闪避) |
这三层是同时成立的,而且都能过——这是好设计。问题只在于"中级以上比新手强太多"(破梦 5 伤 + 无敌,比平A一圈还多)。
4.7 评价
优点: 1. 单帧横扫:反直觉、可学习、奖励"敢靠近"。 2. 距离权重:站远勾引突进,逼你在中距离博弈。 3. 二阶段白给窗口:给了一个明确的"节奏断点",而不是血量翻倍。 4. 重击可打断:把"控制"变成一种主动解法。 5. 视觉信号清楚:横扫有红弧、二阶段红眼 + 血条变色。
问题: 1. 没有一句台词。它是第一章的收尾,却完全没有"人格"。打完没有任何叙事反馈,直接切梦醒。 2. 横扫判定比视觉小:圆心在身前 143、半径 236,但视觉上刀有 118×1.55 ≈ 183 长 + 手臂 62 → 看着能打到 245,实际 236 —— 勉强对得上,但玩家会误判"刀尖擦到"。 3. 跃击几乎不构成威胁:落地无判定、冲击波慢(520)、还能跳过 → 它是"填充招",出现频率却不低。 4. 二阶段只加了一招弹幕,其余完全一样 → 二阶段的"新鲜感"只有 15 秒。
5. Boss「丛林石像」深度解析(掉头版 · 2026-10-27 改版)
5.1 数值与结构
| 项 | 值 | 备注 |
|---|---|---|
| 总 HP | 33 | |
| 掉头阈值 | ≤ 17 | 血量掉到 17 时头掉下来 |
| 掉头后 | 身体 10 血 + 飞头 7 血 | 两个个体同时在场(合计 17) |
| 体型 | 1.9× | 全游戏最大 |
| 移速 | 0(身体不动) | |
| 血条 | 按全部个体剩余血量 / 33 结算 | 掉头后会自动落到约 51% |
5.2 身体(掉头前后都用这两招)
① 落石
| 阶段 | 时长 | 说明 | ||
|---|---|---|---|---|
| 起手 | 0.55 | |||
| 生成 | 瞬间 | 在玩家位置 ±280px 内随机 3 颗 | ||
| 落石 | 0.9 秒预警圈 | 地面红圈放大 + 石头从上砸下,` | dx | < 74` → 2 伤 |
| 结束 | 1.7 |
判定特点:只看 x 不看 y → 跳起来也会被砸中(这次没改,属于遗留问题)。
② 砸地(石拳)
| 阶段 | 时长 | 说明 | ||||
|---|---|---|---|---|---|---|
| 抬手 | 0.5 | 新增:红色落点预警(两个红圈 + 两条红色范围线 + 拳头染红) | ||||
| 判定 | 一帧 | ` | dx | < 270 && | dy | < 150` → 2 伤 + 380 击退 |
| 结束 | 1.1 |
改版前:石拳没有任何红色预警,只有"抬手臂"这个动作 → 它是全游戏唯一一个"不给颜色信号就出手"的招。现在补上了和别的怪一致的红色语言。
掉头后节奏变化:身体的出招间隔从 1.5 秒 → 1.9 秒(两个个体同时压过来太密,稍微放缓)。
5.3 飞头(stone_head.gd,新增)
| 项 | 值 |
|---|---|
| HP | 7 |
| 悬停高度 | 离地约 250px(y≈526) |
| 水平站位 | 保持在玩家一侧约 210px(避免和身体叠在一起) |
| 碰撞 | 不撞地形(collision_mask = 0) |
| 招式 | 时轴 | 判定 | 安全解 |
|---|---|---|---|
| 种子弹(浮瞳同款) | 蓄力 0.45 → 460 速直线弹 | 半径 10 → 命中 32px,1 伤 | 翻滚 / 横向跑 |
| 锁定冲撞 | 瞄准 0.55(红色虚线 + 落点圈)→ 700 速冲 0.55s | 距离 < 86 → 1 伤 + 420 击退 | 翻滚穿过 / 拉开距离 |
| 冲撞后 | 恢复 1.25s,向上飘回悬停高度 | — | 这是打头的窗口 |
为什么悬停 250px:站着平A 的判定框只到 y≈648(离地 132),够不到 526 的头 → 必须跳起来打。这不是刁难,是把"对空"这门课补上:全游戏只有浮瞳需要跳跃,现在石像的飞头也要求。
打头的两个窗口: 1. 跳起来打(跳跃最高点判定框覆盖 475–583,正好罩住 526 附近); 2. 它冲下来之后(冲撞结束的 1.25 秒恢复期,它就在地面高度附近)。
掉头演出(_split()):
Feel.slowmo(0.45, 0.9)慢动作 + 震屏 1.0 + 白闪 + 10 颗碎石粒子;- 玩家获得 1.6 秒无敌(避免刚分裂就被身体 + 头同时夹击);
- HUD 中央提示「头 掉 了」;
- 身体进入 1.8 秒的停顿,头有 1.9–2.4 秒的初始冷却 → 掉头后有约 2 秒的安全输出窗口。

5.4 血条与判定
- HUD 血条由
Arena._process每帧按(身体 hp + 头 hp) / 33计算,
所以掉头瞬间会从"约 52%"继续往下走,不会重置成满血。
- 两个个体都死才算打赢:
Arena维护_boss_parts数组,最后一个个体死亡时才播 Boss 收尾白幕。 - 只杀头不杀身体(或反之)都不会结束战斗。
5.5 为什么这样改
| 改版前 | 改版后 |
|---|---|
| 33 血、2 招、无二阶段、纯站桩 | 33 血、两段式(身体 + 飞头)、5 个招式来源 |
| 打 40–60 秒,看同一招 12 次以上 | 前 16 血一个节奏,掉头后换一套节奏 |
| 石拳无预警(不公平) | 石拳有红色落点圈 |
| 打完就没了,没有任何"阶段感" | 掉头是明确的"阶段转折"(慢动作 + 无敌 + 提示) |
5.6 仍存在的问题
1. 落石不看 y → 跳跃无法规避,与"跳能躲地面攻击"的约定冲突。 2. 飞头的受击体偏小(圆形半径 34 × 1.25 ≈ 42),玩家跳打时容易"看着碰到了却没判定"。 3. 头和身体可能同时出手,虽然各自节奏放缓了,但极端情况仍会叠加(实测无辅助时仍会死 2–5 次)。 4. 掉头后身体只剩"落石 + 砸地",缺少一个新招来匹配"半血变强"的预期——现在的强度变化主要来自"多了一个敌人",而不是"身体变强了"。
5.7 评价
这是全游戏唯一一个"两段式"Boss:前半段考"躲 AOE + 找输出窗口",后半段考"同时处理地面和空中"。它终于从"一块会还手的沙袋"变成了"一场有转折的战斗"。
代价是难度明显上升(自动操作实测死亡从 1 次变成 2–5 次),如果后面要继续调,最容易的两处是:给飞头一个"被打晕就掉下来"的机制(把空中目标变成地面目标),或者把身体掉头后的血再降一点。
6. 两个 Boss 的对比
| 维度 | 假面 | 丛林石像 |
|---|---|---|
| 设计目标 | 考"读招 + 位置" | 考"耐力" |
| 招式 | 4 + 阶段 | 2 |
| 位置博弈 | 有(距离权重) | 无(它不动) |
| 玩家主动性 | 重击可打断、完美闪避接破梦 | 只能躲 + 打 |
| 叙事角色 | 无台词 | 无台词(只有主角吐槽) |
| 难度来源 | 突进快、连段多 | HP 厚、时间长 |
| 完成度 | ★★★★ | ★★☆ |
一句话对比:
假面是"会跟你下棋的对手",石像是"一块会还手的沙袋"。
7. 问题清单(按严重度,带修法)
2026-10-27 注:#1–#4、#6 已经改掉了(藤蔓的必中 / 减速穿透无敌帧 / 6 秒禁翻滚 / 无冷却;石像的砸地预警 + 新增「掉头」两段式)。下表保留原判断,方便对照改动前后的差别。
| # | 问题 | 严重度 | 修法(成本从低到高) |
|---|---|---|---|
| 1 | 藤蔓抽打必中(无距离检查) | 🔴 致命 | 加 if absf(dx) < 220 判断,2 行 |
| 2 | 藤蔓减速穿透无敌帧 | 🔴 致命 | 把 apply_vine_slow 移进 hurt() 里,或判断 _iframes |
| 3 | 减速 6s 且禁翻滚、无解除 | 🔴 致命 | 缩到 2.5s;或允许"减速时也能滚(只是慢)";或加"连续按键挣脱" |
| 4 | 藤蔓 0 冷却(0.95s 一轮) | 🟠 高 | 加 1.2–1.6s 冷却 |
| 5 | 野猪只是"更肉的奔角" | 🟠 高 | 加一个"二段冲锋 / 撞墙后反击"的小变招;或降到 6 血 |
| 6 | 石拳无红色预警 | 🟠 高 | 画一个 270px 红色扇形,3 行 |
| 7 | 落石不看 y(跳跃无效) | 🟡 中 | 加 target.y < ground+80 判断,或改成"必须走出圈" |
| 8 | 石像无二阶段、33 血 | 🟡 中 | 降到 28 血;或半血加"落石 ×5 + 地震" |
| 9 | 浮瞳只有一种弹 | 🟡 中 | 加"三连发 / 追踪 / 延迟爆炸"任一变体 |
| 10 | 假面无台词、无叙事反馈 | 🟡 中 | 登场 + 半血各加 1–2 句(boss_intro 字段已支持) |
| 11 | 敌人受击硬直 0.22s + 重击眩晕 1.0s = 无限控 | 🟡 中 | 给精英/Boss 加"眩晕抗性递增" |
| 12 | 缺"反翻滚/反跳跃/反重击"手段 | 🟡 中 | 加持续判定(>0.28s)、对空攻击、霸体 |
| 13 | 缺精英怪档位 | 🟡 中 | 做"野猪 + 藤蔓"的复合精英,或"影卒队长(3 连刺)" |
| 14 | 藤蔓视觉高 170、受击体只有 ~70px | 🟢 低 | 覆写 _build_body 用更高的胶囊 |
| 15 | 木桩用 9999 血实现"打不死" | 🟢 低 | 加 invulnerable 标记(语义更清楚) |
8. 如果要加新怪:现有骨架能直接复用什么
这套代码加一个怪的最低成本是 ~40 行:
class_name MyEnemy
extends Enemy
func _ready() -> void:
max_hp = 5; radius = 26.0; body_top = -80.0
super._ready(); scale = Vector2(1.4, 1.4)
func _think(delta: float) -> void: # 状态机
...
func _contact_hit_active() -> bool: # 接触伤害白名单
return state == "lunge"
func body_color() -> Color: return Color("#...")
func accent_color() -> Color: return Color("#...")
func _draw_body(col, pulse) -> void: ... # 程序化绘制
能直接白拿的东西:重力、受击白闪、血条、眩晕星星、死亡爆散、镜头夹取、defeated 信号、_hurt_stun、stun()。
必须自己写的:状态机、判定时机、预警绘制。 最容易写错的(这轮 review 出的经验): 1. 用 _touch_damage 之前一定要自己检查距离——基类不查。 2. _contact_hit_active() 决定"什么时候贴身会打人",写错会出现"全程贴身掉血"或"永远打不到"。 3. 视觉尺寸和 _build_body() 的碰撞胶囊要匹配,否则"打不到"。 4. 预警一定要用红色(玩家已经被训练成"红=滚")。
*附:实机截图 playtest-通关实录/;工程改动指南 续作开发基础-v0.2.md;整体解析 游戏解析-全面解析.md。*