diff --git a/Game/scripts/match_mode.gd b/Game/scripts/match_mode.gd index d8219f16..1bf58bee 100644 --- a/Game/scripts/match_mode.gd +++ b/Game/scripts/match_mode.gd @@ -30,6 +30,7 @@ const KICKOFF_COUNTDOWN_SECONDS := 3 var match_timer: Timer var _in_overtime := false var _match_over := false +var _last_timer_remaining := -1 func _get_arena_scene_path() -> String: @@ -64,7 +65,9 @@ func _make_opponent_controller() -> ShipController: func _process(_delta): if match_timer and match_timer.time_left > 0: var remaining := ceili(match_timer.time_left) - timer_updated.emit(floori(remaining / 60.0), remaining % 60) + if remaining != _last_timer_remaining: + _last_timer_remaining = remaining + timer_updated.emit(floori(remaining / 60.0), remaining % 60) func _on_goal_scored(conceding_team: int) -> void: diff --git a/TODO.md b/TODO.md index 8cf13cc6..0a7df77f 100644 --- a/TODO.md +++ b/TODO.md @@ -18,7 +18,7 @@ Bugs found in an adversarial review. None are gameplay- or physics-affecting, so - [x] Collapse the four disagreeing team palettes into one source of truth — `ship.gd`, `HUDController.gd` and `goal.gd` each declare `TEAM_COLORS`, `arena_boundary.gd` exports `team0_tint`/`team1_tint`, and `arena_deck.gdshader` defaults to a fifth pair. Three of them disagree, so nose, goal rim, end zone and scoreboard are all different blues. - [ ] Goal scoring volume (3.5 x 1.5, `objects/goal.tscn`) is smaller than the drawn mouth (3.7 x 1.65, `ArenaBoundary.GOAL_APERTURE_*`) — a ball crossing the visible edge doesn't score. Derive the aperture constants from the goal's collision shape, the way `goal.gd:53` already measures its own visuals. - [x] `match_mode.gd`: full time can fire mid-kickoff-countdown, and the stalled coroutine resumes into the dying scene (can re-emit `kickoff_countdown` / unfreeze bodies for a frame). Guard `_run_kickoff_countdown` with a match-over flag. -- [ ] `match_mode.gd` emits `timer_updated` every frame for a value that changes once a second; the HUD re-formats and re-shapes the label each time. Emit only on change, matching `ship.gd`'s threshold-gated telemetry discipline. +- [x] `match_mode.gd` emits `timer_updated` every frame for a value that changes once a second; the HUD re-formats and re-shapes the label each time. Emit only on change, matching `ship.gd`'s threshold-gated telemetry discipline. - [ ] `HUDController` binds to `get_first_node_in_group("ship")` in a group that always has 2+ members — works only because the player ship happens to spawn first. Have the game mode hand the HUD its target ship. - [ ] Reuse a member `ShipAction` in `ship.gd` (controllerless path) and `player_ship_controller.gd` instead of allocating one per physics tick; `ai_ship_controller.gd` already does this correctly. - [ ] Delete the duplicate 1 MB texture — `assets/textures/planet_surface.png` and `assets/models/nebula_planet_planet_surface.png` are byte-identical.