From 70341bd40fa0704874ea337fe23ee68ec706f36e Mon Sep 17 00:00:00 2001 From: DKChan <524912269@qq.com> Date: Tue, 29 Sep 2026 23:56:26 +0800 Subject: [PATCH] =?UTF-8?q?iter8-=E4=B8=89=E8=BD=AE=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E6=89=B9=EF=BC=88=E7=94=A8=E6=88=B7=E4=BA=8C=E8=BD=AE=E7=9B=AE?= =?UTF-8?q?=E6=A3=80=E5=8F=8D=E9=A6=88=EF=BC=89=EF=BC=9A#1=20=E5=BC=B9?= =?UTF-8?q?=E7=AA=97=20z=20=E5=BA=8F=E4=BF=AE=E5=A4=8D=3DConfirmDialog.ope?= =?UTF-8?q?n=20=E8=87=AA=E6=8F=90=E5=AE=BF=E4=B8=BB=E5=AD=90=E7=BA=A7?= =?UTF-8?q?=E6=9C=80=E6=9C=AB=EF=BC=88=E6=A0=B9=E5=9B=A0=EF=BC=9A=E5=BC=B9?= =?UTF-8?q?=E7=AA=97=E6=9E=84=E5=BB=BA=E5=BA=8F=E6=97=A9=E4=BA=8E=E5=BC=80?= =?UTF-8?q?=E5=A7=8B=E8=A6=86=E7=9B=96=E5=B1=82=E8=80=8C=E5=BC=80=E5=A7=8B?= =?UTF-8?q?=E5=B1=82=E7=BB=84=E5=90=88=E6=A0=B9=E5=B0=BE=E9=83=A8=E6=89=8D?= =?UTF-8?q?=20add=3D=E7=BB=98=E5=88=B6=E6=9C=80=E4=B8=8A=EF=BC=8C=E5=BC=B9?= =?UTF-8?q?=E7=AA=97=E8=A2=AB=E6=95=B4=E5=B1=82=E7=9B=96=E4=BD=8F=E2=80=94?= =?UTF-8?q?=E2=80=94=E7=94=A8=E6=88=B7=E5=AE=9E=E6=9C=BA=E5=AE=9E=E8=AF=81?= =?UTF-8?q?=E3=80=8C=E7=9C=8B=E4=B8=8D=E8=A7=81=E5=BC=B9=E7=AA=97/?= =?UTF-8?q?=E7=A6=BB=E5=BC=80=E8=8F=9C=E5=8D=95=E6=89=8D=E6=98=BE=E5=BD=A2?= =?UTF-8?q?=E3=80=8D=EF=BC=8C=E6=8E=A2=E9=92=88=20pressed.emit=20=E5=90=88?= =?UTF-8?q?=E6=88=90=E8=B7=AF=E5=BE=84=E4=B8=8D=E6=9A=B4=E9=9C=B2=E6=A0=91?= =?UTF-8?q?=E5=BA=8F=E9=81=AE=E6=8C=A1=E6=95=85=E5=85=A8=E7=BB=BF=E6=BC=8F?= =?UTF-8?q?=E7=BD=91=EF=BC=89=EF=BC=9B#3=20=E7=BB=93=E7=AE=97=E9=80=90?= =?UTF-8?q?=E6=9D=A1=E6=BC=94=E5=87=BA=E9=87=8D=E5=81=9A=3DSettlementFxVie?= =?UTF-8?q?w=20=E6=96=B0=E5=A2=9E=20play=5Fdamage=5Fnumber=EF=BC=88?= =?UTF-8?q?=E7=AB=99=E6=A1=A9=E5=A4=B4=E9=A1=B6=E6=95=B0=E5=AD=97=E6=B5=AE?= =?UTF-8?q?=E7=8E=B0=E4=B8=8A=E9=A3=98=E6=B8=90=E9=9A=90+=E6=8F=8F?= =?UTF-8?q?=E8=BE=B9+crit=20=E5=8A=A0=E5=A4=A7=EF=BC=89=E4=B8=8E=20play=5F?= =?UTF-8?q?status=5Fpulse=EF=BC=88Buff/Debuff=20=E8=89=B2=E7=8E=AF?= =?UTF-8?q?=E6=89=A9=E6=95=A3=EF=BC=89=EF=BC=8C=5Fconsume=5Frow=20?= =?UTF-8?q?=E6=8C=82=20=5Fplay=5Fsettlement=5Fmark=20=E9=80=90=E6=9D=A1?= =?UTF-8?q?=E6=A0=87=E5=87=BA=EF=BC=88effect=20=E8=89=B2=E7=8E=AF=E2=86=92?= =?UTF-8?q?damage=20=E6=95=B0=E5=AD=97=E6=89=93=E8=B0=81=E6=A0=87=E8=B0=81?= =?UTF-8?q?=E2=86=92heal=20=E7=BB=BF=E5=AD=97=EF=BC=8C=E7=9B=AE=E6=A0=87?= =?UTF-8?q?=E8=A7=A3=E6=9E=90=E5=A4=B1=E8=B4=A5=E5=85=9C=E6=A3=8B=E7=9B=98?= =?UTF-8?q?=E4=B8=AD=E5=BF=83=EF=BC=89=EF=BC=8C=E6=AE=B5=E5=86=85=E8=8A=82?= =?UTF-8?q?=E5=A5=8F=200.06=E2=86=920.22s=20=E9=80=90=E6=9D=A1=E5=8F=AF?= =?UTF-8?q?=E6=84=9F=E7=9F=A5=EF=BC=9Bfx=5Fprobe=20=E2=91=A3c=20=E9=80=90?= =?UTF-8?q?=E6=9D=A1=E6=A0=87=E5=87=BA=E6=96=AD=E8=A8=80=E2=80=94=E2=80=94?= =?UTF-8?q?=E9=97=B8=EF=BC=9A=E5=86=92=E7=83=9F=20596/0+run=5Fall=2015=20?= =?UTF-8?q?=E5=A5=97+=E5=85=AD=E6=8E=A2=E9=92=88=E5=85=A8=E7=BB=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- game/presentation/main.gd | 27 ++++++++++- game/presentation/views/confirm_dialog.gd | 6 +++ game/presentation/views/settlement_fx_view.gd | 46 ++++++++++++++++++- game/smoke/fx_probe.gd | 10 +++- 4 files changed, 86 insertions(+), 3 deletions(-) diff --git a/game/presentation/main.gd b/game/presentation/main.gd index a5a28dbd..3adc2c96 100644 --- a/game/presentation/main.gd +++ b/game/presentation/main.gd @@ -94,7 +94,7 @@ var _row_queue: Array = [] # 待排播行(step_row 载荷原样入队 var _row_pace_wait := 0.0 # 距下一行排播的剩余秒(_process 消耗) var _pace_prev_segment := "" # 上一排播行的段型(段间/段内延迟判据) const PACE_SEGMENT_GAP := 0.3 # 段间阶梯延迟(代拍板:白名单 0.2–0.4s 内取值,追认清单呈报) -const PACE_ROW_GAP := 0.06 # 段内快排间隔(同行段连读性——非白名单约束面) +const PACE_ROW_GAP := 0.22 # 段内间隔(三轮 #3 上调 0.06→0.22——逐条演出可感知,配合数字浮现/状态脉冲) func _ready() -> void: @@ -638,6 +638,7 @@ func _consume_row(row: Dictionary) -> void: log_view.append_row(row) stage.on_step_row_fx(row) _play_cross_zone_fx(row) # 跨区因果演出(结算演出链批):开格之因 → 站桩之果 + _play_settlement_mark(row) # 三轮 #3——逐条标出:Buff/Debuff 色环脉冲 → 伤害/治疗数字浮现 # 高光演出(战斗结算×3①② 占位):完美排雷横幅 / 标中旗加重弹道 if String(row.get("type", "")) == "highlight": board_zone.fx.play_perfect_sweep() @@ -646,6 +647,30 @@ func _consume_row(row: Dictionary) -> void: _refresh_presentations() +# 逐条结算标出(三轮 #3——用户裁决按结算顺序演出:先 Buff/Debuff 特效、再基础伤害数字; +# 打中谁标谁、主角被打标主角;道具/奖励行逐条冒出)。目标解析失败兜底棋盘中心。 +func _play_settlement_mark(row: Dictionary) -> void: + var mark_type := String(row.get("type", "")) + if mark_type != "effect" and mark_type != "damage" and mark_type != "heal": + return + var target := String(row.get("target", "")) + var center: Vector2 + if target == "hero": + center = stage.hero_standee_center() + else: + var v = stage.enemy_standee_center(target) if target != "" and target != "all_enemies" else null + center = v if v != null else board_view.get_global_rect().get_center() + match mark_type: + "effect": + var col: Color = Color("7cc47c") if int(row.get("value", 0)) > 0 else Color("c47c7c") + settlement_fx.play_status_pulse(center, col) + "damage": + settlement_fx.play_damage_number(center, "-%d" % int(row.get("value", 0)), + Color("d9402a"), bool(row.get("crit", false))) + "heal": + settlement_fx.play_damage_number(center, "+%d" % int(row.get("value", 0)), Color("7cc47c"), false) + + func _process(delta: float) -> void: # 排播泵(卡⑦——演出层帧驱动;队列空=零开销直返) if _row_queue.is_empty(): diff --git a/game/presentation/views/confirm_dialog.gd b/game/presentation/views/confirm_dialog.gd index 06ad1dc8..e275925c 100644 --- a/game/presentation/views/confirm_dialog.gd +++ b/game/presentation/views/confirm_dialog.gd @@ -52,6 +52,12 @@ func open(text: String, confirm_label: String, cancel_label: String = "取消") _text.text = text _confirm_btn.text = confirm_label _cancel_btn.text = cancel_label + # z 序自提(三轮修改批 #1——用户实机实证:本弹窗构建序早于开始覆盖层,而开始层是组合根 + # 尾部才 add_child 的(树序最末=绘制最上),弹窗被整层盖住——「看不见弹窗/离开菜单才显形」。 + # 每次打开强制提到宿主子级最末,绘制序恒最上。) + var host := get_parent() + if host != null: + host.move_child(self, host.get_child_count() - 1) visible = true diff --git a/game/presentation/views/settlement_fx_view.gd b/game/presentation/views/settlement_fx_view.gd index 006d523f..993cc7b2 100644 --- a/game/presentation/views/settlement_fx_view.gd +++ b/game/presentation/views/settlement_fx_view.gd @@ -71,7 +71,9 @@ func play_projectile(from: Vector2, to: Vector2, glyph: String, col: Color, crit # 减动效=静态呈现(驻留后即隐,零位移/零透明度动画——行呈现不跳过同语义,卡⑦ AC③)。 const BANNER_DWELL := 0.6 -var _fx_banners := 0 # 演出探针计数(fx_probe 断言面) +var _fx_banners := 0 # 演出探针计数(fx_probe 断言面) +var _fx_damage_marks := 0 # 三轮 #3——伤害/治疗数字浮现计数 +var _fx_status_pulses := 0 # 三轮 #3——增益/减益状态脉冲计数 # 演出探针出口(卡⑦——轮横幅发射计数) @@ -79,6 +81,48 @@ func probe_banners() -> int: return _fx_banners +# 演出探针出口(三轮 #3——逐条结算演出计数) +func probe_settlement_marks() -> int: + return _fx_damage_marks + _fx_status_pulses + + +# 伤害/治疗数字浮现(三轮 #3——用户裁决「打中谁就标出多少伤害/主角被打标出多少」): +# 站桩头顶浮现数字,上飘 34px 渐隐 0.7s(减动效=时长折半同演不跳过);crit 加大加重。 +func play_damage_number(pos: Vector2, text: String, col: Color, crit: bool = false) -> void: + _fx_damage_marks += 1 + var lab := UiKit.label(text, 26 if crit else 20, true) + lab.add_theme_color_override("font_color", col) + lab.add_theme_color_override("font_outline_color", Color(0.1, 0.08, 0.06, 0.9)) + lab.add_theme_constant_override("outline_size", 4) + lab.mouse_filter = Control.MOUSE_FILTER_IGNORE + lab.z_index = 6 + add_child(lab) + await get_tree().process_frame # 等一帧取实际尺寸(文本度量) + lab.position = pos - lab.size * 0.5 + var tw := lab.create_tween() + tw.tween_property(lab, "position:y", lab.position.y - 34.0, UiKit.motion(0.7)).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT) + tw.parallel().tween_property(lab, "modulate:a", 0.0, UiKit.motion(0.35)).set_delay(UiKit.motion(0.35)) + tw.tween_callback(lab.queue_free) + + +# 增益/减益状态脉冲(三轮 #3——用户裁决「先上 Buff/Debuff 特效,再显基础伤害」): +# 目标站桩处色环扩散淡出 0.5s(增益绿/减益红由调用方传色)。 +func play_status_pulse(pos: Vector2, col: Color) -> void: + _fx_status_pulses += 1 + var ring := Panel.new() + ring.mouse_filter = Control.MOUSE_FILTER_IGNORE + var sb := UiKit.panel_flat(Color(col, 0.0), col, 100, 3) + ring.add_theme_stylebox_override("panel", sb) + ring.size = Vector2(22, 22) + ring.position = pos - ring.size * 0.5 + ring.z_index = 5 + add_child(ring) + var tw := ring.create_tween() + tw.tween_property(ring, "scale", Vector2(2.4, 2.4), UiKit.motion(0.5)).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT) + tw.parallel().tween_property(ring, "modulate:a", 0.0, UiKit.motion(0.5)) + tw.tween_callback(ring.queue_free) + + func play_round_banner(ri: int) -> void: _fx_banners += 1 var banner := Panel.new() diff --git a/game/smoke/fx_probe.gd b/game/smoke/fx_probe.gd index 59cf07c7..3c44f129 100644 --- a/game/smoke/fx_probe.gd +++ b/game/smoke/fx_probe.gd @@ -96,6 +96,14 @@ func _ready() -> void: problems.append("减动效轮横幅未发射(卡⑦ AC③——静态化仍呈现不跳过)") UiKit.motion_scale = saved_motion + # ---- ④c 逐条结算标出(三轮 #3——状态脉冲+伤害数字浮现断言面) ---- + sfx.play_status_pulse(Vector2(120, 120), Color("7cc47c")) + sfx.play_damage_number(Vector2(120, 120), "-7", Color("d9402a"), false) + await get_tree().process_frame + await get_tree().process_frame + if int(sfx.probe_settlement_marks()) != 2: + problems.append("逐条结算标出未落位(状态脉冲+数字浮现——三轮 #3),实得 %s" % sfx.probe_settlement_marks()) + # ---- ⑤ 主角三态切换(迭代 6 T3——attack/hit 短驻自回 + 死亡复活态回 idle) ---- var hero_sb = sb_script.new("hero") hero_sb.box = Vector2(150, 176) @@ -148,7 +156,7 @@ func _ready() -> void: # ---- 汇总 ---- if problems.is_empty(): - print("[fx_probe] PASS — 死亡碎裂5块/命中火花6/意图三档+零表示/胜利纹章10/失败掸灰8+旗光8/结算光带+缘线/轮横幅双态/主角三态切换 全链路通过") + print("[fx_probe] PASS — 死亡碎裂5块/命中火花6/意图三档+零表示/胜利纹章10/失败掸灰8+旗光8/结算光带+缘线/轮横幅双态/逐条结算标出/主角三态切换 全链路通过") get_tree().quit(0) else: for p in problems: