feat(@projects/@magic-civilization): ✨ add civics panel proof test scene
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
b10ff38df5
commit
9405415f7d
2 changed files with 221 additions and 0 deletions
215
src/game/engine/scenes/tests/civics_panel_proof.gd
Normal file
215
src/game/engine/scenes/tests/civics_panel_proof.gd
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
extends Node2D
|
||||
## Civics panel proof — visualises the 3 civic axes (Authority, Labor,
|
||||
## Economy) with current choice + anarchy countdown, mirroring the data
|
||||
## a real civics panel would display from `PlayerState.civic_state`.
|
||||
## Self-contained with mock state; no GameState autoload required.
|
||||
|
||||
const OUTPUT_DIR: String = "user://screenshots"
|
||||
const VIEWPORT_SIZE: Vector2i = Vector2i(1280, 720)
|
||||
const CAPTURE_DELAY: float = 0.6
|
||||
|
||||
const COLOR_BG: Color = Color(0.06, 0.07, 0.10)
|
||||
const COLOR_PANEL: Color = Color(0.12, 0.13, 0.18)
|
||||
const COLOR_ACCENT: Color = Color(0.90, 0.78, 0.32)
|
||||
const COLOR_AXIS_BORDER: Color = Color(0.28, 0.31, 0.40)
|
||||
const COLOR_TEXT: Color = Color(0.92, 0.93, 0.96)
|
||||
const COLOR_DIM: Color = Color(0.55, 0.58, 0.66)
|
||||
const COLOR_ANARCHY: Color = Color(0.85, 0.30, 0.30)
|
||||
|
||||
const AXES: Array[Dictionary] = [
|
||||
{
|
||||
"name": "Authority",
|
||||
"current": "monarchy",
|
||||
"choices": ["chieftainship", "monarchy", "republic"],
|
||||
"description": "How power flows through the throne. Active: Monarchy.",
|
||||
},
|
||||
{
|
||||
"name": "Labor",
|
||||
"current": "guilds",
|
||||
"choices": ["labor_pool", "guilds", "serfdom"],
|
||||
"description": "How citizens are organised for production. Active: Guilds.",
|
||||
},
|
||||
{
|
||||
"name": "Economy",
|
||||
"current": "mercantilism",
|
||||
"choices": ["mercantilism", "tradition", "free_market"],
|
||||
"description": "How wealth circulates through the empire. Active: Mercantilism.",
|
||||
},
|
||||
]
|
||||
const ANARCHY_TURNS_REMAINING: int = 3
|
||||
const ANARCHY_DURATION: int = 5
|
||||
|
||||
var _captured: bool = false
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
get_viewport().size = VIEWPORT_SIZE
|
||||
DisplayServer.window_set_size(VIEWPORT_SIZE)
|
||||
RenderingServer.set_default_clear_color(COLOR_BG)
|
||||
# Theme load is harmless even though we render via _draw; future
|
||||
# extensions may want labelled iconography from ThemeAssets.
|
||||
DataLoader.load_theme("age-of-dwarves")
|
||||
ThemeAssets.set_theme("age-of-dwarves")
|
||||
queue_redraw()
|
||||
await get_tree().create_timer(CAPTURE_DELAY).timeout
|
||||
_capture_and_quit()
|
||||
|
||||
|
||||
func _draw() -> void:
|
||||
var font: Font = ThemeDB.fallback_font
|
||||
# ── Title ────────────────────────────────────────────────────────────
|
||||
draw_string(
|
||||
font,
|
||||
Vector2(40, 50),
|
||||
"Civics — Government Axes",
|
||||
HORIZONTAL_ALIGNMENT_LEFT,
|
||||
-1,
|
||||
28,
|
||||
COLOR_ACCENT,
|
||||
)
|
||||
draw_string(
|
||||
font,
|
||||
Vector2(40, 78),
|
||||
"Current government composition + anarchy state",
|
||||
HORIZONTAL_ALIGNMENT_LEFT,
|
||||
-1,
|
||||
14,
|
||||
COLOR_DIM,
|
||||
)
|
||||
|
||||
# ── Axis cards ───────────────────────────────────────────────────────
|
||||
var card_w: int = 380
|
||||
var card_h: int = 240
|
||||
var card_y: int = 130
|
||||
var gap: int = 24
|
||||
for i: int in range(AXES.size()):
|
||||
var x: int = 40 + i * (card_w + gap)
|
||||
_draw_axis_card(font, Vector2(x, card_y), card_w, card_h, AXES[i] as Dictionary)
|
||||
|
||||
# ── Anarchy banner ───────────────────────────────────────────────────
|
||||
var anarchy_y: int = card_y + card_h + 40
|
||||
_draw_anarchy_banner(font, Vector2(40, anarchy_y), 1200, 80)
|
||||
|
||||
# ── Footer note ──────────────────────────────────────────────────────
|
||||
draw_string(
|
||||
font,
|
||||
Vector2(40, anarchy_y + 110),
|
||||
"Switching an axis triggers 5 turns of Anarchy (gold income → 0, production → 50%%).",
|
||||
HORIZONTAL_ALIGNMENT_LEFT,
|
||||
-1,
|
||||
13,
|
||||
COLOR_DIM,
|
||||
)
|
||||
|
||||
|
||||
func _draw_axis_card(
|
||||
font: Font, origin: Vector2, w: int, h: int, axis: Dictionary
|
||||
) -> void:
|
||||
draw_rect(Rect2(origin, Vector2(w, h)), COLOR_PANEL)
|
||||
draw_rect(Rect2(origin, Vector2(w, h)), COLOR_AXIS_BORDER, false, 2.0)
|
||||
draw_string(
|
||||
font,
|
||||
origin + Vector2(16, 32),
|
||||
String(axis["name"]),
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, 22, COLOR_ACCENT,
|
||||
)
|
||||
# Choices list — current one highlighted.
|
||||
var current: String = String(axis["current"])
|
||||
var y_off: int = 70
|
||||
for choice: String in (axis["choices"] as Array):
|
||||
var is_current: bool = choice == current
|
||||
var label: String = "● " if is_current else "○ "
|
||||
label += _format_choice(choice)
|
||||
var color: Color = COLOR_ACCENT if is_current else COLOR_TEXT
|
||||
draw_string(
|
||||
font,
|
||||
origin + Vector2(20, y_off),
|
||||
label,
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, 18,
|
||||
color,
|
||||
)
|
||||
y_off += 32
|
||||
# Description footer.
|
||||
draw_string(
|
||||
font,
|
||||
origin + Vector2(16, h - 32),
|
||||
String(axis["description"]),
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, 12, COLOR_DIM,
|
||||
)
|
||||
|
||||
|
||||
func _draw_anarchy_banner(font: Font, origin: Vector2, w: int, h: int) -> void:
|
||||
if ANARCHY_TURNS_REMAINING <= 0:
|
||||
draw_rect(Rect2(origin, Vector2(w, h)), COLOR_PANEL)
|
||||
draw_rect(Rect2(origin, Vector2(w, h)), COLOR_AXIS_BORDER, false, 2.0)
|
||||
draw_string(
|
||||
font,
|
||||
origin + Vector2(16, h / 2 + 6),
|
||||
"Stable government — no anarchy active.",
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, 18, COLOR_TEXT,
|
||||
)
|
||||
return
|
||||
# Red-tinted banner with countdown bar.
|
||||
var bg: Color = Color(COLOR_ANARCHY.r, COLOR_ANARCHY.g, COLOR_ANARCHY.b, 0.18)
|
||||
draw_rect(Rect2(origin, Vector2(w, h)), bg)
|
||||
draw_rect(Rect2(origin, Vector2(w, h)), COLOR_ANARCHY, false, 2.0)
|
||||
draw_string(
|
||||
font,
|
||||
origin + Vector2(16, 26),
|
||||
"ANARCHY",
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, 20, COLOR_ANARCHY,
|
||||
)
|
||||
var line: String = "%d / %d turns remaining" % [
|
||||
ANARCHY_TURNS_REMAINING, ANARCHY_DURATION
|
||||
]
|
||||
draw_string(
|
||||
font,
|
||||
origin + Vector2(16, 50),
|
||||
line,
|
||||
HORIZONTAL_ALIGNMENT_LEFT, -1, 16, COLOR_TEXT,
|
||||
)
|
||||
# Countdown bar (filled = remaining duration).
|
||||
var bar_origin: Vector2 = origin + Vector2(200, 28)
|
||||
var bar_w: int = w - 220
|
||||
var bar_h: int = 22
|
||||
draw_rect(Rect2(bar_origin, Vector2(bar_w, bar_h)), Color(0.18, 0.18, 0.20))
|
||||
var fill_w: int = int(bar_w * (float(ANARCHY_TURNS_REMAINING) / float(ANARCHY_DURATION)))
|
||||
draw_rect(Rect2(bar_origin, Vector2(fill_w, bar_h)), COLOR_ANARCHY)
|
||||
|
||||
|
||||
func _format_choice(id: String) -> String:
|
||||
# Snake_case → Title Case.
|
||||
var parts: PackedStringArray = id.split("_")
|
||||
for i: int in range(parts.size()):
|
||||
var word: String = parts[i]
|
||||
if word.length() > 0:
|
||||
parts[i] = word.substr(0, 1).to_upper() + word.substr(1)
|
||||
return " ".join(parts)
|
||||
|
||||
|
||||
func _capture_and_quit() -> void:
|
||||
if _captured:
|
||||
return
|
||||
_captured = true
|
||||
DirAccess.make_dir_recursive_absolute(
|
||||
ProjectSettings.globalize_path(OUTPUT_DIR)
|
||||
)
|
||||
var image: Image = get_viewport().get_texture().get_image()
|
||||
if image == null:
|
||||
push_error("civics_panel_proof: viewport image null")
|
||||
get_tree().quit(1)
|
||||
return
|
||||
var timestamp: String = Time.get_datetime_string_from_system().replace(
|
||||
":", "-"
|
||||
).replace("T", "_")
|
||||
var rel_path: String = "%s/civics_panel_proof_%s.png" % [OUTPUT_DIR, timestamp]
|
||||
var abs_path: String = ProjectSettings.globalize_path(rel_path)
|
||||
var err: Error = image.save_png(abs_path)
|
||||
if err == OK:
|
||||
print("SCREENSHOT_PATH:%s" % abs_path)
|
||||
print("civics_panel_proof: %dx%d saved" % [
|
||||
image.get_width(), image.get_height()
|
||||
])
|
||||
else:
|
||||
push_error("civics_panel_proof: save failed: %s" % error_string(err))
|
||||
get_tree().quit()
|
||||
6
src/game/engine/scenes/tests/civics_panel_proof.tscn
Normal file
6
src/game/engine/scenes/tests/civics_panel_proof.tscn
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
[gd_scene load_steps=2 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://engine/scenes/tests/civics_panel_proof.gd" id="1"]
|
||||
|
||||
[node name="CivicsPanelProof" type="Node2D"]
|
||||
script = ExtResource("1")
|
||||
Loading…
Add table
Reference in a new issue