diff --git a/CargoCounter.gd b/CargoCounter.gd new file mode 100644 index 0000000..bf060f7 --- /dev/null +++ b/CargoCounter.gd @@ -0,0 +1,33 @@ +extends NeonNumber + +# What the fleet is CARRYING, shown under the banked total (#15, part 2 of +# #12). Since #14 ore is cargo until the fleet delivers it to the mothership, +# so without this, mining visibly does nothing - the banked figure above does +# not move until the fleet flies home, which reads as gathering being broken. +# +# Three things separate it from the banked readout, because colour alone is a +# weak signal on a phone screen in a game that is mostly teal: +# - amber rather than ore-teal, the same amber used elsewhere for ore in +# transit (the extractor derrick, the hauler route) +# - smaller, sitting UNDER the banked figure: subordinate to it, because +# this is the number that is not yours yet +# - present only while actually carrying something, so an empty hold is not +# a permanent zero taking up space next to the real total +# +# Reads GameState directly for the same reason ResourceCounter does: it stays +# correct across the space <-> planet-surface scene swap with nobody having +# to push updates into it. + +const CARGO_GLOW: Color = Color(1.0, 0.78, 0.25) +const CARGO_CORE: Color = Color(0.22, 0.12, 0.0) + + +func _ready() -> void: + glow_color = CARGO_GLOW + core_color = CARGO_CORE + + +func _process(_delta: float) -> void: + visible = GameState.fleet_cargo > 0 + if visible: + set_amount(GameState.fleet_cargo) diff --git a/CargoCounter.gd.uid b/CargoCounter.gd.uid new file mode 100644 index 0000000..dfef251 --- /dev/null +++ b/CargoCounter.gd.uid @@ -0,0 +1 @@ +uid://bmrcja23g5oi6 diff --git a/Main.tscn b/Main.tscn index 7cf3a8e..c830b41 100644 --- a/Main.tscn +++ b/Main.tscn @@ -21,6 +21,7 @@ [ext_resource type="Script" path="res://NeonNumber.gd" id="19"] [ext_resource type="Script" path="res://NeonPanel.gd" id="20"] [ext_resource type="Script" path="res://SkillTreeView.gd" id="21"] +[ext_resource type="Script" path="res://CargoCounter.gd" id="22"] [sub_resource type="ShaderMaterial" id="1"] shader = ExtResource("5") @@ -89,6 +90,15 @@ offset_bottom = 92 script = ExtResource("16") digit_height = 60.0 +[node name="CargoCounter" type="Control" parent="UI"] +mouse_filter = 2 +offset_left = 28 +offset_top = 96 +offset_right = 320 +offset_bottom = 146 +script = ExtResource("22") +digit_height = 42.0 + [node name="PlanetNameLabel" type="Label" parent="UI"] visible = false offset_left = 24 diff --git a/tests/_cargo_readout_preview.gd b/tests/_cargo_readout_preview.gd new file mode 100644 index 0000000..6e63b47 --- /dev/null +++ b/tests/_cargo_readout_preview.gd @@ -0,0 +1,15 @@ +extends Node2D + +# Preview, not a test. The resource readouts with the fleet carrying ore, so +# the #15 banked-vs-carried split can actually be looked at - headless draws +# no pixels and cannot say whether two numbers read as two different things. +# +# bash tests/screenshot.sh res://tests/_cargo_readout_preview.tscn /tmp/hud.png 20 720x1280 + + +func _ready() -> void: + GameState.buildings.clear() + GameState.extractors.clear() + GameState.rocks = 128 + GameState.fleet_cargo = 34 + add_child(load("res://Main.tscn").instantiate()) diff --git a/tests/_cargo_readout_preview.tscn b/tests/_cargo_readout_preview.tscn new file mode 100644 index 0000000..60c3692 --- /dev/null +++ b/tests/_cargo_readout_preview.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3] + +[ext_resource type="Script" path="res://tests/_cargo_readout_preview.gd" id="1"] + +[node name="CargoReadoutPreview" type="Node2D"] +script = ExtResource("1") diff --git a/tests/test_cargo_readout.gd b/tests/test_cargo_readout.gd new file mode 100644 index 0000000..03b2500 --- /dev/null +++ b/tests/test_cargo_readout.gd @@ -0,0 +1,117 @@ +extends SceneTree + +# Headless gameplay test: run with +# godot --headless -s res://tests/test_cargo_readout.gd +# Forgejo #15 (part 2 of #12): what the fleet is carrying has to be visible +# separately from what is banked. +# +# Since #14, ore is cargo until the fleet delivers it to the mothership. The +# banked readout does not move on pickup, so without a second readout mining +# looks broken - you gather ore and no number on screen changes. +# +# --headless has no GPU and draws no pixels, so this asserts on the two +# readouts' state, not on their appearance. tests/screenshot.sh covers +# whether they are legible. +# +# Verifies: +# 1. the banked readout keeps showing the BANK, not the total +# 2. the cargo readout shows the hold, and appears only while carrying +# 3. an empty hold hides it rather than parking a permanent 0 beside the +# real total +# 4. delivering moves the number from one readout to the other +# 5. the two are actually told apart on screen, rather than being the same +# number twice in the same colour at the same place + +var game_state: Node +var scene: Node +var banked: Control +var cargo: Control +var stage: int = 0 +var elapsed: float = 0.0 + + +func _initialize() -> void: + game_state = root.get_node("GameState") + game_state.buildings.clear() + game_state.extractors.clear() + game_state.rocks = 42 + game_state.fleet_cargo = 0 + scene = load("res://Main.tscn").instantiate() + root.add_child(scene) + banked = scene.get_node("UI/ResourceCounter") + cargo = scene.get_node("UI/CargoCounter") + + +func _process(delta: float) -> bool: + elapsed += delta + match stage: + 0: + if elapsed < 0.2: + return false + # --- 3. nothing carried -> no cargo readout ----------------- + if cargo.visible: + print("TEST_CARGO_READOUT: FAIL (cargo readout showing with an empty hold)") + quit(1) + return true + if banked.amount != 42: + print("TEST_CARGO_READOUT: FAIL (banked readout shows %d, bank is 42)" % banked.amount) + quit(1) + return true + print("empty hold -> cargo readout hidden, banked shows %d" % banked.amount) + + game_state.collect_cargo(7) + elapsed = 0.0 + stage = 1 + return false + 1: + if elapsed < 0.2: + return false + # --- 1 + 2. carried and banked are separate numbers --------- + if not cargo.visible: + print("TEST_CARGO_READOUT: FAIL (carrying 7 and the cargo readout is hidden)") + quit(1) + return true + if cargo.amount != 7: + print("TEST_CARGO_READOUT: FAIL (cargo readout shows %d, hold is 7)" % cargo.amount) + quit(1) + return true + if banked.amount != 42: + print("TEST_CARGO_READOUT: FAIL (banked readout moved to %d on a pickup - it is showing the total, not the bank)" % banked.amount) + quit(1) + return true + print("carrying 7 -> cargo=%d banked=%d" % [cargo.amount, banked.amount]) + + # --- 5. genuinely distinguishable --------------------------- + if cargo.glow_color == banked.glow_color: + print("TEST_CARGO_READOUT: FAIL (both readouts drawn in the same colour)") + quit(1) + return true + if cargo.position == banked.position: + print("TEST_CARGO_READOUT: FAIL (both readouts in the same place)") + quit(1) + return true + print("distinct: colours %s vs %s, at %s vs %s" % [ + cargo.glow_color, banked.glow_color, cargo.position, banked.position + ]) + + # --- 4. delivery moves it across ---------------------------- + game_state.deliver_cargo() + elapsed = 0.0 + stage = 2 + return false + 2: + if elapsed < 0.2: + return false + if cargo.visible: + print("TEST_CARGO_READOUT: FAIL (cargo readout still showing after delivery)") + quit(1) + return true + if banked.amount != 49: + print("TEST_CARGO_READOUT: FAIL (banked shows %d after delivering 7 into 42)" % banked.amount) + quit(1) + return true + print("delivered -> cargo hidden, banked shows %d" % banked.amount) + print("TEST_CARGO_READOUT: PASS") + quit(0) + return true + return false diff --git a/tests/test_fleet_cargo.gd.uid b/tests/test_fleet_cargo.gd.uid new file mode 100644 index 0000000..3c5062a --- /dev/null +++ b/tests/test_fleet_cargo.gd.uid @@ -0,0 +1 @@ +uid://c2y4e2f1rgera