Files
gplan-2/game/presentation/views/battle_end_overlay.gd
T

122 lines
4.5 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# VERTICAL SLICE - NOT FOR PRODUCTION
# 实现 GDD:design/ux/battle.md(胜利/失败终局 overlay——金蜡封占位落于扫雷图区中央 + 判定行 +
# 明细回看入口 + 继续/返回;失败 = 暮蓝 #5A6C8C 氛围(明度不变)+ 旗化光点收回占位;
# pattern 6 模态 overlay 层级纪律——遮挡物隐藏/输入锁定断言归场景探针)。
# Date: 2026-09-12(扩展自 node_overlay 的战斗终局职责分离)
class_name BattleEndOverlay
extends Control
signal review_pressed
signal continue_pressed
const COL_GOLD := UiKit.GOLD
const COL_DUSK := UiKit.DUSK # 暮蓝(全作唯一暮蓝档)
const COL_WARM := UiKit.WARM
var _dim: ColorRect
var _seal: Panel
var _verdict: Label
var _review_btn: Button
var _btn: Button
var _board_rect := Rect2()
func _init() -> void:
_dim = ColorRect.new()
_dim.color = Color(COL_WARM, 0.0)
_dim.set_anchors_preset(Control.PRESET_FULL_RECT)
add_child(_dim)
var center := CenterContainer.new()
center.set_anchors_preset(Control.PRESET_FULL_RECT)
_dim.add_child(center)
var box := VBoxContainer.new()
box.add_theme_constant_override("separation", 12)
center.add_child(box)
_verdict = UiKit.label("", 26, true)
_verdict.add_theme_color_override("font_color", COL_WARM)
_verdict.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
box.add_child(_verdict)
_review_btn = UiKit.button("明细回看")
_review_btn.pressed.connect(func(): review_pressed.emit())
box.add_child(_review_btn)
_btn = UiKit.button("继续")
_btn.pressed.connect(func(): continue_pressed.emit())
box.add_child(_btn)
# 金蜡封占位(胜利):圆形色块落于扫雷图区中央——位置由 set_board_rect 注入
_seal = Panel.new()
_seal.mouse_filter = Control.MOUSE_FILTER_IGNORE
var sb := UiKit.panel_flat(COL_GOLD, UiKit.GOLD_DEEP, 200, 4)
_seal.add_theme_stylebox_override("panel", sb)
_seal.size = Vector2(72, 72)
_seal.visible = false
_seal.top_level = true
add_child(_seal)
visible = false
# 终局画面数据锚 = 战斗结算 判定行(verdict)——判定行文案由组合根装配传入
func open_victory(verdict_line: String, continue_label: String, board_rect: Rect2) -> void:
_dim.color = Color(COL_WARM, 0.28)
_verdict.text = verdict_line
_verdict.add_theme_color_override("font_color", UiKit.INK_ON_GOLD)
_btn.text = continue_label
_board_rect = board_rect
visible = true
_play_seal_fall()
_play_flag_recall(0) # 胜利不放旗收回
func open_defeat(verdict_line: String, continue_label: String, board_rect: Rect2) -> void:
# 明度不变的暮蓝色相氛围(全屏唯一暮蓝档——§2.5 最静一拍)
_dim.color = Color(COL_DUSK, 0.45)
_verdict.text = verdict_line
_verdict.add_theme_color_override("font_color", COL_WARM)
_btn.text = continue_label
_board_rect = board_rect
visible = true
_seal.visible = false
_play_flag_recall(8)
func close() -> void:
visible = false
_seal.visible = false
func is_open() -> bool:
return visible
func verdict_text() -> String:
return _verdict.text
# 金蜡封自上落下弹跳定格于棋盘中央(§2.4 克制不狂欢——占位级)
func _play_seal_fall() -> void:
var target := _board_rect.get_center() - _seal.size * 0.5
if _board_rect.size == Vector2.ZERO:
target = get_viewport_rect().size * 0.5 - _seal.size * 0.5
_seal.position = Vector2(target.x, -100.0)
_seal.visible = true
var tw := _seal.create_tween()
tw.tween_property(_seal, "position:y", target.y - 26.0, UiKit.motion(0.42)).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_IN)
tw.tween_property(_seal, "position:y", target.y, UiKit.motion(0.22)).set_trans(Tween.TRANS_BOUNCE).set_ease(Tween.EASE_OUT)
# 旗化光点收回(失败——插过的旗逐面化光点收回占位,§2.5)
func _play_flag_recall(count: int) -> void:
for i in count:
var dot := ColorRect.new()
dot.color = COL_GOLD
dot.size = Vector2(6, 6)
var base := _board_rect.get_center() if _board_rect.size != Vector2.ZERO else get_viewport_rect().size * 0.5
dot.position = base + Vector2((float(i % 5) - 2.0) * _board_rect.size.x * 0.14 if _board_rect.size.x > 0 else 0.0,
(float(i % 3) - 1.0) * _board_rect.size.y * 0.18) # 确定性散布(S2 禁全局随机——占位演出同守)
dot.mouse_filter = Control.MOUSE_FILTER_IGNORE
add_child(dot)
var tw := dot.create_tween()
tw.tween_interval(UiKit.motion(0.1 * i))
tw.tween_property(dot, "position:y", dot.position.y - 120.0, UiKit.motion(0.8))
tw.parallel().tween_property(dot, "modulate:a", 0.0, UiKit.motion(0.8))
tw.tween_callback(dot.queue_free)