Add engine flames, damage numbers, nameplates, music, and combat/collision fixes
Feature work (CLAUDE.md items 17-18): - Race roster art rework (Apex/ISN/ORC) plus per-ship engine-flame sprites that swap in on thrust - Floating damage-number VFX, per-ship nameplates, energy bar rework - Background music manager and per-race ship SFX Bugfixes/tuning from live testing: - No friendly fire: bullets stop on a teammate's hull but deal no damage (bullet.gd), decided by race via PlayerRegistry - Ships no longer physically block each other (own collision layer, ship.tscn/bullet.tscn) -- fixes ramming/parking trolling and the stuck-on- corpse bug after a kill - Explosions ghost any ship's sprite passing through instead of blocking it (effects/explosion.gd's GhostArea) - Fixed two "flushing physics queries" crashes from the above: explosion spawn and death/respawn collision toggling are now deferred (ship_movement.gd) - Dead ships stop blocking bullets during their respawn delay - Bots fly a mixed roster (1 Tank + 2 Gunner + rest Fighter per team) instead of always the Fighter (bot_manager.gd) - Camera zoom knob, larger/longer-lived damage numbers and nameplate text, red (not yellow) enemy name color for better contrast Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -38,6 +38,8 @@ README for how to run/extend it.
|
||||
16. **Real game-server pool (self-registration + heartbeat + stale sweep)** — `NetworkManager.host_server()` now calls the new `MatchmakingClient.register_server()` once on boot and then every `HEARTBEAT_INTERVAL` (8s) via a `Timer`, reporting live `PlayerRegistry.players.size()`/`MAX_PLAYERS` — item 15's demo-seeded rows are no longer the only thing populating `GET /servers`; a real server registering on the same `(ip, port, mode)` as a demo row just takes it over in place, no special-casing needed. `--server-ip=` is a new cmdline arg for the IP a hosted server advertises (defaults to loopback for local dev — see the reachability note already in `matchmaking-api/README.md` about `DEV_SEED_SERVER_IP`, same constraint applies here). API-side, `POST /servers/register` now computes `status` from `player_count`/`max_players` (`full` vs `available`) instead of always writing `available`, and a new background loop (`sweep_stale_servers` in `app/routers/servers.py`, run every 5s from `main.py`'s lifespan) marks any server `offline` once its `last_heartbeat` exceeds `server_stale_seconds` (20s) — catches a crashed/killed server that never got to deregister cleanly, so a dead server doesn't sit in the list looking joinable forever. `menu/server_select.gd`'s connect button now also blocks (with a message) on `status == "full"`, not just `"offline"`.
|
||||
17. **Race roster replaced (Terran/Mechanos/Vorg → Apex Dynamics/Inner Sphere Navy/Outer Rim Collective)** — `team_select.gd`'s `RACES` now points at the 3 factions from `overview/racesclasses.md`'s pivot, each with a 3-ship Fighter/Gunner/Tank roster (Lancet/Pulsar/Sovereign, Patriot/Barrage/Behemoth, Rail-Jack/Scrap-Spitter/Iron-Clad) instead of the old 5-ship Interceptor/Gunship/Bomber/Support/Heavy set; `SPEED_BY_ROLE` shrunk to match. Art was extracted from 3 user-provided concept sheets (originally dropped at `assets/images/ship/`, now cropped per-ship into `assets/images/ships/apex|isn|orc/` with a `source/` copy of each sheet, same convention as the old race folders) — background removed via flood-fill + largest-connected-component matting (plain background for Apex, starfield for ORC, grid-lined UI panels for ISN, each needing different thresholding). ISN and ORC's source art was drawn nose-*sideways*; both were rotated 90° before saving since this project's ship rotation convention is nose-up at `rotation = 0` (`Vector2.UP.rotated(rotation)` in `ship_movement.gd`) — Apex's source art was already nose-up. `scale` values were computed with the same per-role target-on-screen-height normalization the old roster used (Fighter/Gunner/Tank targets reuse the old Interceptor/Gunship/Heavy heights, ~52.5/58.5/82.5px) so ship sizes read consistently across factions. Verified by hosting a real server and screenshotting bot fill flying with the new sprites — no load errors, transparency and nose-up orientation both correct. The old `terran/mech/vorg` asset folders are left on disk but unreferenced (no code points at them); not deleted since that wasn't asked for.
|
||||
|
||||
18. **Engine-flame sprite swap on thrust** — 6 of item 17's 9 ships (ISN's Patriot/Barrage/Behemoth, ORC's Rail-Jack/Scrap-Spitter/Iron-Clad) gained a second `_flame.png` sprite alongside their idle one, cropped from the same concept sheets' flame-frame columns (ISN's sheet has a clean idle/flame pair per ship; ORC's only unambiguous case was Rail-Jack's brighter 3rd-column flame, so Scrap-Spitter/Iron-Clad's flame PNGs are just copies of their idle sprite for now — their sheet's other columns are damage/weapon-fire poses, not more exhaust). Behemoth's flame was composited from two separate sheet crops (clean idle hull + a flame-only crop of just its thrusters) rather than cropped directly, since the sheet's flame frame has a large red shield-ability graphic overlapping the hull that isn't exhaust. Apex's 3 ships (Lancet/Pulsar/Sovereign) have no flame art — their concept sheet never drew a thrust pose — so they're untouched and always show their one sprite. Wired into gameplay via a new optional `flame_path` per ship in `team_select.gd`'s `RACES`, threaded through `PlayerRegistry` (`submit_local_loadout`/`register_bot`/the loadout RPCs, new `ship_flame_path` field, default `""`) so bots and remote peers all get it too, not just the local owner. `ship_movement.gd`'s `_set_thrust_sprite()` swaps the `Sprite2D` texture based on whether the up/down thrust key is *currently held*, not current speed — this game's movement has no drag, so a first cut keyed off `velocity.length()` left the flame on long after letting off the gas since a released ship keeps drifting at speed. The owner predicts this locally the instant it samples input (`_owner_tick`); the server does the same for bots/itself (`_server_tick`) and broadcasts its authoritative value as a new `thrusting` bool on the existing `_receive_state` RPC so every other peer's view of a ship — which never sees raw input, only replicated state — stays in sync too, with no separate RPC needed. Ships with no `flame_path` (Apex) just skip the check entirely (`_flame_texture == null` short-circuits).
|
||||
|
||||
## Current Tasks
|
||||
|
||||
- [ ] Asteroids and environment hazards
|
||||
|
||||
Reference in New Issue
Block a user