Generalize the resource HUD readouts #49
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Foundation ticket - the black-hole and gas-burner tickets both add a resource and both need this first.
Why
Adding ore and gas to the HUD was done with four hand-placed nodes per scene and one
NeonNumbersubclass each:Main.tscnandPlanetSurface.tscneach containUI/ResourceCounter(banked ore),UI/GasCounter(banked gas),UI/CargoCounter(fleet ore),UI/GasCargoCounter(fleet gas).ResourceCounter.gd,GasCounter.gd,CargoCounter.gd,GasCargoCounter.gd- the last two are subclasses that exist purely to re-read a differentGameStatefield.So a third resource currently costs two more hand-placed nodes in two scenes plus two more script files. Everything else in the game is already resource-agnostic:
Inventory,ResourceBar, andResourceTransferListall iterateGameState.resource_types()and pick up a newResourceDefinitionwith no code change. The HUD is the last hardcoded surface.Scope
ResourceReadout.gd(extends Control) that builds one row perGameState.resource_types()at_ready():ResourceGlyph(which already resolvesdefinition.glyph_scene),GameState.resource_color(id),Color(1.0, 0.78, 0.25), seeCargoCounter.gd's comment on why in-transit is a different colour),NeonNumberfor the digits rather than plainLabels, so the HUD keeps its current look.Main.tscnandPlanetSurface.tscnwith a singleResourceReadoutoccupying the same screen region. Preserve the current arrangement as closely as possible: banked column top-left under aBANKEDcaption, fleet column top-right underFLEET HOLD.PlanetSurfaceController._compose_surface()currently themes../UI/BankCaption,../UI/FleetCaptionand../UI/CaptureLabelfrom the surface profile. Keep whatever captions survive on that list so the gas surface still recolours them.ResourceCounter.gd,GasCounter.gd,CargoCounter.gd,GasCargoCounter.gdonce nothing references them.tests/test_cargo_readout.gdreadsUI/ResourceCounterandUI/CargoCounterdirectly (lines 47-48) - update it to the new node, keeping the same assertions about what the player can see.Out of scope
Changing any
ResourceDefinition, or adding new resources - that's the gas-burner and black-hole tickets.Acceptance criteria
.trestoResourceDefinitions.DEFINITIONS/ORDERmakes a new HUD row appear in both scenes with no scene edit and no new script. Prove it with a scratch definition in the test, then remove it.res://Main.tscnandres://PlanetSurface.tscnagainst the current build.bash tests/run_tests.sh cargo,run_tests.sh gas, and the full suite pass.Tests
New
tests/test_resource_readout.gd(row-per-resource, hide-at-zero, third-resource pickup), plus the updatedtests/test_cargo_readout.gd. Screenshots of both scenes at 720x1280.Repo notes (read before starting)
/storage/emulated/0/GodotProjects/SpaceshipTest.touchon it. Android FUSE does not bump mtime under~/storage/shared, and Godot's import cache will silently keep serving the old version, making a correct fix look like it did nothing.bash tests/run_tests.sh <substring>; full suite with no argument. Tests areSceneTreescripts printingTEST_NAME: PASS/TEST_NAME: FAIL (reason)and callingquit(0|1)- copy the shape oftests/test_capture_points.gd.bash tests/screenshot.sh <res://Scene.tscn> <out.png> <frames> 720x1280. Use few frames (~15); the software rasterizer is slow.--headlessrenders nothing at all, so it cannot validate visuals.NeonDraw/NeonPiece; do not introduce a different visual idiom.*Definitionresources plus capability component scenes. Do not addif type == "..."branches.FileAccess, nouser://).GameStateis an in-memory autoload. Do not invent a save system.Traps that have already cost hours on this codebase
const X = preload(...)in a test file that is itself the-sentry point. It evaluates during that file's own early compilation, which can run before autoloads are registered; any script it pulls in that referencesGameStateinside a function body then fails to compile withIdentifier not found: GameState. Usevar X: Scriptplusload()inside_initialize()instead. See the header comment intests/test_capture_points.gd.[]to a typedArray[Resource]export from another script fails at runtime - the compiler only sees the target asResourceand cannot confirm the element type. Leave the declared default alone, or build the typed array inside the owning script.Fleet.spawn_ships(0, ...)does not empty the fleet - it falls back to one default interceptor by design. Clearfleet.shipsexplicitly if a test or preview needs genuinely zero ships.ship.positionwithout also settingship.move_targetletsShip._physics_processsteer it straight back toward the stale target within a few frames.SceneTreetest's own_process()clock under device load, even with--fixed-fps 60. Gate waits on the system's own state (a component's timer or flag), not onelapsed >= duration.queue_free()s itself (projectiles, shells) must not be re-read inside a per-frame wait condition - cache the scalar you need before the wait._screenshot_tool.gd's_initialize(), so their_ready()races the game scene's own_ready(). Do setup on the first_process()tick, andget_tree().paused = trueonce everything is placed if the scene must hold still.Done in commit
0582181, pushed to main.Replaced ResourceCounter/GasCounter/CargoCounter/GasCargoCounter (one hardcoded node+script per resource, times two scenes) with a single
ResourceReadout.gdthat builds one banked + one fleet-hold row perGameState.resource_types()entry at_ready(). A new resource added toResourceDefinitionsnow gets a HUD row automatically, no scene edit or new script needed.Preserves the existing look exactly: BANKED column left, FLEET HOLD column right, amber fleet-in-transit color, and the ore-on-bright-surface contrast on
PlanetSurface.tscn(now abright_backgroundexport flag instead of per-node color overrides). Reuses the already-genericResourceGlyphfor icons instead ofNeonNumber's hardcoded ore hexagon.Tests:
tests/test_resource_readout.gd(new) - per-resource row mapping, hide-at-zero semantics, live updates, visual distinctness, a static check that the script has no hardcoded resource id, and thatPlanetSurface.tscn's instance setsbright_background.tests/test_cargo_readout.gd(updated) - same coverage as before, now against the generic readout.Screenshots at 720x1280 confirm legibility against the acceptance criterion:
Along the way, found and fixed a real bug in the existing
test_cargo_readout.gd: it looked up its readout nodes immediately afteradd_child()in_initialize(), butResourceReadoutbuilds its rows in_ready(), which for a-sentry-point script does not fire synchronously inside thatadd_child()- it's deferred to the next frame. Moved the lookup to after the test's existing elapsed-time wait in_process().Also confirmed empirically (new repo note, worth keeping in mind for future tickets): a
-sentry-point test script can reach an autoload's CONSTANTS via the bare identifier (GameState.RESOURCE_ORE) anywhere, but calling any of its METHODS that way (GameState.resource_types()) fails to compile with "Identifier not found: GameState", even from_initialize(). Route method calls through the actual instance (root.get_node("GameState")) instead, like the rest of the suite already does.