From 03c77e64f3a1d436bd60d2ed1cef91bcb407fec2 Mon Sep 17 00:00:00 2001 From: Wickedness Date: Sat, 20 Jun 2026 06:06:21 +0900 Subject: [PATCH] Polish board unit labels with generated surfaces --- README.md | 1 + scripts/scenes/battle_scene.gd | 47 +++++++++++++++++++++++++++++----- tools/smoke_visual_assets.gd | 13 ++++++++++ 3 files changed, 54 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 8be5206..17ddbc6 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ Godot 4 tactical RPG prototype inspired by classic turn-based Romance of the Thr - Battlefield hover info badges use generated jade panel texture plus terrain, supply, tactic, objective, and threat icons, keeping raw grid coordinates out of visible play text. - Battle, top-toolbar, and pre-battle command buttons now prefer generated high-resolution bronze/parchment icon art under `art/ui/icons` and generated lacquer/jade/cinnabar button surfaces under `art/ui/buttons`, with procedural icon drawing and flat button styles kept only as fallbacks. - Battle maps blend generated terrain texture tiles for plains, forests, hills, wasteland, roads, water, villages, and castles over the high-resolution battlefield backdrop, with generated transparent feature overlays for road connections, water, villages, castles, and wasteland accents. +- Board unit nameplates and HP bars use generated jade panel surfaces so the high-resolution sprites are not paired with flat black UI strips. - Core UI panels now prefer generated high-resolution lacquer, scroll, jade, and command-seal frame textures under `art/ui/panels`, with the calmer ink/wood/jade flat styles kept as fallbacks instead of the earlier yellow, hard-edged frame treatment. - Pre-battle Chapters overview shows story-arc progress with map thumbnail rows, compact status badges, hover details, and can open completed or current battles. - Pre-battle Save menu can write and load one manual campaign checkpoint separate from the automatic save, using compact seal-style slot rows and hover checkpoint details. diff --git a/scripts/scenes/battle_scene.gd b/scripts/scenes/battle_scene.gd index a1bd807..164d084 100644 --- a/scripts/scenes/battle_scene.gd +++ b/scripts/scenes/battle_scene.gd @@ -5859,10 +5859,7 @@ func _draw_units() -> void: _draw_unit_facing_marker(rect, unit, team_color, sprite_modulate) var hp_ratio := float(unit["hp"]) / float(max(1, int(unit["max_hp"]))) - var hp_back := Rect2(rect.position + Vector2(8, TILE_SIZE - 8), Vector2(TILE_SIZE - 16, 5)) - var hp_front := Rect2(hp_back.position, Vector2(hp_back.size.x * hp_ratio, hp_back.size.y)) - draw_rect(hp_back, Color(0.08, 0.08, 0.09)) - draw_rect(hp_front, _unit_hp_color(hp_ratio)) + _draw_unit_hp_bar(rect, hp_ratio) _draw_unit_status_markers(center, hp_ratio, unit) if selected_unit and not selection_frame_drawn: @@ -5967,12 +5964,48 @@ func _draw_unit_nameplate(rect: Rect2, label: String) -> void: if label.is_empty(): return var font := _draw_ui_font(true) - var label_rect := Rect2(rect.position + Vector2(4.0, TILE_SIZE - 21.0), Vector2(TILE_SIZE - 8.0, 13.0)) - draw_rect(label_rect, Color(0.025, 0.018, 0.012, 0.76)) - draw_rect(label_rect, Color(UI_OLD_BRONZE.r, UI_OLD_BRONZE.g, UI_OLD_BRONZE.b, 0.48), false, 1.0) + var label_rect := _unit_nameplate_rect(rect) + _draw_generated_badge_panel( + label_rect, + Color(UI_OLD_BRONZE.r, UI_OLD_BRONZE.g, UI_OLD_BRONZE.b, 0.74), + Color(0.025, 0.018, 0.012, 0.62), + _unit_board_panel_key(), + 0.08, + 1.0 + ) _draw_ink_text(font, label_rect.position + Vector2(0, 10), label, HORIZONTAL_ALIGNMENT_CENTER, label_rect.size.x, 9, UI_PARCHMENT_TEXT) +func _draw_unit_hp_bar(rect: Rect2, hp_ratio: float) -> void: + var bar_rect := _unit_hp_bar_rect(rect) + _draw_generated_badge_panel( + bar_rect, + Color(UI_TARNISHED_BRONZE.r, UI_TARNISHED_BRONZE.g, UI_TARNISHED_BRONZE.b, 0.70), + Color(0.020, 0.018, 0.015, 0.66), + _unit_board_panel_key(), + 0.06, + 1.0 + ) + var fill_width := maxf(0.0, (bar_rect.size.x - 2.0) * clampf(hp_ratio, 0.0, 1.0)) + if fill_width <= 0.0: + return + var fill_rect := Rect2(bar_rect.position + Vector2(1.0, 1.0), Vector2(fill_width, maxf(1.0, bar_rect.size.y - 2.0))) + draw_rect(fill_rect, _unit_hp_color(hp_ratio)) + draw_rect(Rect2(fill_rect.position, Vector2(fill_rect.size.x, 1.0)), Color(1.0, 0.96, 0.72, 0.20)) + + +func _unit_nameplate_rect(rect: Rect2) -> Rect2: + return Rect2(rect.position + Vector2(4.0, TILE_SIZE - 22.0), Vector2(TILE_SIZE - 8.0, 14.0)) + + +func _unit_hp_bar_rect(rect: Rect2) -> Rect2: + return Rect2(rect.position + Vector2(7.0, TILE_SIZE - 8.0), Vector2(TILE_SIZE - 14.0, 6.0)) + + +func _unit_board_panel_key() -> String: + return "hud_jade" + + func _target_selection_marker_entries() -> Array[Dictionary]: if basic_attack_targeting: return _attack_target_marker_entries() diff --git a/tools/smoke_visual_assets.gd b/tools/smoke_visual_assets.gd index 9bf193c..25bf863 100644 --- a/tools/smoke_visual_assets.gd +++ b/tools/smoke_visual_assets.gd @@ -3326,6 +3326,19 @@ func _check_hud_focus_text(failures: Array[String]) -> void: facing_points_inside = false if not facing_points_inside: failures.append("Unit facing marker should stay anchored inside its tile: %s" % str(facing_marker_points)) + if scene._unit_board_panel_key() != "hud_jade": + failures.append("Board unit nameplate and HP bar should use generated jade panel art") + if scene._load_art_texture("res://art/ui/panels/panel_%s.png" % scene._unit_board_panel_key()) == null: + failures.append("Board unit nameplate and HP bar should load generated panel texture") + var board_unit_rect: Rect2 = scene._visual_rect_for_unit(cao_cao) + var nameplate_rect: Rect2 = scene._unit_nameplate_rect(board_unit_rect) + var hp_bar_rect: Rect2 = scene._unit_hp_bar_rect(board_unit_rect) + if not facing_tile_rect.encloses(nameplate_rect): + failures.append("Unit nameplate should stay inside its tile: %s within %s" % [str(nameplate_rect), str(facing_tile_rect)]) + if not facing_tile_rect.encloses(hp_bar_rect): + failures.append("Unit HP bar should stay inside its tile: %s within %s" % [str(hp_bar_rect), str(facing_tile_rect)]) + if nameplate_rect.intersects(hp_bar_rect): + failures.append("Unit nameplate should not collide with HP bar: %s / %s" % [str(nameplate_rect), str(hp_bar_rect)]) _check_unit_class_family(failures, scene, "cao_cao", "tactic") _check_unit_class_family(failures, scene, "xiahou_dun", "cavalry") _check_unit_class_family(failures, scene, "yellow_turban_2", "infantry")