diff --git a/game/presentation/views/level_map_screen.gd b/game/presentation/views/level_map_screen.gd index ac72e134..82901172 100644 --- a/game/presentation/views/level_map_screen.gd +++ b/game/presentation/views/level_map_screen.gd @@ -40,6 +40,7 @@ const TITLE_FORK := "选择下一节点" # 岔路停点 const NODE_HALF := Vector2(26, 18) # 节点方块半宽高(52×36 占位画布参数——样张批终稿) const HIT_PAD := 6.0 # 图上命中外扩(指宽容差) const CONFIRM_WINDOW_S := 3.0 # 放弃确认态窗口(秒——超时回落) +const COL_HP_BAR_BACK := Color8(40, 34, 28) # 迷你血条深底(样张 v1 冻结——对暗面板可辨) var _runner = null var _title: Label @@ -58,6 +59,8 @@ var abandon_btn: Button # 放弃入口(可见性归组合根 set_ var _abandon_armed := false # 二次确认态(首击置位、二击提交、超时/重开回落) var _confirm_left := 0.0 # 确认态剩余秒数(_process 倒计时+脉冲驱动) var _node_icons := {} # 节点图标贴图(load_tex 守卫——缺位 null → 字形回退,冒烟/无素材检出安全) +var _noise_rect: TextureRect # 屏底石纹(换层色板渐变承载面——null = 纯色回退无挂点) +var _tint_level := 0 # 当前已应用 tint 的层号(0 = 未应用) func _init() -> void: @@ -78,6 +81,7 @@ func _init() -> void: tex.set_anchors_preset(Control.PRESET_FULL_RECT) tex.mouse_filter = Control.MOUSE_FILTER_IGNORE base.add_child(tex) + _noise_rect = tex # 世界侧 tint 承载面(换层色板渐变挂点——§2.7 切片档) var center := CenterContainer.new() center.set_anchors_preset(Control.PRESET_FULL_RECT) base.add_child(center) @@ -126,8 +130,11 @@ func _init() -> void: _bonus_row.add_child(bonus_box) var bonus_inner := VBoxContainer.new() bonus_box.add_child(bonus_inner) - bonus_inner.add_child(UiKit.label("本关加成", 12, false)) + var bonus_cap := UiKit.label("本关加成", 12, false) + bonus_cap.add_theme_color_override("font_color", UiKit.WARM_SOFT) + bonus_inner.add_child(bonus_cap) _bonus_value = UiKit.label("", 15, true) + _bonus_value.add_theme_color_override("font_color", UiKit.WARM) bonus_inner.add_child(_bonus_value) bottom.add_child(_bonus_row) var spacer := Control.new() @@ -141,19 +148,23 @@ func _init() -> void: visible = false -# 状态数据框工厂(直角细线数据框——pattern 5 族;hp_box = 带迷你血条) +# 状态数据框工厂(直角细线数据框——pattern 5 族;hp_box = 带迷你血条。墨色按样张 v1 冻结: +# 暗底标签 WARM_SOFT/读数 WARM——§7.1 数据素面墨来自世界的墨在暗底侧的落法,L3 ≥4.5:1) func _status_box(caption: String, with_bar: bool) -> PanelContainer: var panel := PanelContainer.new() panel.add_theme_stylebox_override("panel", UiKit.panel_flat(UiKit.DARK_UPCOMING, UiKit.PANEL_BORDER, 0, 1)) var inner := VBoxContainer.new() panel.add_child(inner) - inner.add_child(UiKit.label(caption, 12, false)) + var cap := UiKit.label(caption, 12, false) + cap.add_theme_color_override("font_color", UiKit.WARM_SOFT) + inner.add_child(cap) if with_bar: _hp_bar = Control.new() _hp_bar.custom_minimum_size = Vector2(120, 6) _hp_bar.draw.connect(_draw_hp_bar.bind(_hp_bar)) inner.add_child(_hp_bar) var value := UiKit.label("", 15, true) + value.add_theme_color_override("font_color", UiKit.WARM) inner.add_child(value) if caption == "生命": _hp_value = value @@ -163,13 +174,13 @@ func _status_box(caption: String, with_bar: bool) -> PanelContainer: func _draw_hp_bar(bar: Control) -> void: - # 迷你血条(占位:暗底+金填充——比例 = hero_hp / effective_max_hp) + # 迷你血条(样张 v1 冻结:深底 Color8(40,34,28)(对暗面板可辨)+金填充——比例 = hero_hp / effective_max_hp) if _runner == null: return var max_hp := maxi(1, _runner.effective_max_hp()) var ratio := clampf(float(_runner.hero_hp) / float(max_hp), 0.0, 1.0) var full := Rect2(Vector2.ZERO, bar.size) - bar.draw_rect(full, UiKit.DARK_UPCOMING) + bar.draw_rect(full, COL_HP_BAR_BACK) if ratio > 0.0: bar.draw_rect(Rect2(Vector2.ZERO, Vector2(bar.size.x * ratio, bar.size.y)), UiKit.GOLD) @@ -233,6 +244,7 @@ func open_choices(cands: Array, runner) -> void: _cand_ids.append(_id_of(cand)) _fit_canvas(_runner.nodes()) _refresh_status() + _apply_level_tint(int(_runner.level_row.get("level_index", 0))) visible = true if not was_visible: # 独立屏淡入(spec Transitions:约 200ms;alpha 淡入非明度变化——art-bible §2 明度恒定) @@ -261,6 +273,22 @@ func _fit_canvas(nodes: Array) -> void: _canvas.custom_minimum_size = _content_size +# 换层色板渐变挂点(art-bible §2.7 下探过渡切片档——关卡结算确认→下一关→独立屏淡入链路上的 +# 色相层进预告:屏底世界侧随层进换挡,信息层恒定;tint 明度带归一≈1 只动色相/饱和)。 +# tint 候选方向 = art-bible §6.3 三关图类型色板方向(1 dungeon 暖石基准/2 underdark 冷蓝灰/3 deep 灰黑金属), +# 终值归色板样张批——本批只落挂点(level-map.md States 换层进入行承载)。 +const BOARD_TINTS := {1: Color(1, 1, 1), 2: Color(0.84, 0.99, 1.28), 3: Color(0.97, 0.99, 1.09)} + + +func _apply_level_tint(level_index: int) -> void: + if _noise_rect == null or level_index == _tint_level: + return + _tint_level = level_index + var target: Color = BOARD_TINTS.get(level_index, Color(1, 1, 1)) + var tw := create_tween() + tw.tween_property(_noise_rect, "modulate", target, UiKit.motion(0.45)) + + # 状态栏刷新(命令式纪律——组合根打开本屏/兑付确认回执后重查;零推送信号订阅) func _refresh_status() -> void: if _runner == null: