Every bright star in sky_nebula.png reused the exact same diffraction- spike stamp, just relocated. Commit the generator (recovered from an ephemeral scratchpad) to tools/textures/gen_nebula_sky.py, randomize each hero star's rotation, arm count, spike length, and brightness, and regenerate the texture.
14 KiB
TODO
Deferred work, in rough priority order. The current architecture (ShipAction/ShipController seam, Arena/GameMode split, code-driven spawning, group-tagged ball/goals) was chosen specifically so these bolt on without rework.
AI opponent (reinforcement learning)
The training pipeline is built — see TRAINING.md (self-play PPO via the vendored godot_rl_agents bridge, JSON policy export, in-game GDScript inference, eval ladder). Remaining:
- Promote a first tier:
curric-s6-unmaskcopied intoGame/bots/promoted/easy.jsonas the shipped "easy" bot (see TRAINING.md's "Promoted bots" section) —match.tscn/spectate.tscnnow default there instead ofrun05.json. - Long training runs on the Linux/3090 box to produce actually-good bots; promote further checkpoints into
Game/bots/promoted/asmedium/hardtiers once they cleareasy.jsoninevaluate.py. - Staged curriculum (score → defend → avoid draws → full mechanics) via
train.py's--opponent-mode/--draw-penalty/--attack-goal-bias/--vertical-ramp/--pitch-roll-rampflags — see TRAINING.md's "Curriculum training" section.--opponent-mode=frozenis a single-fixed-model slice of the league idea below, not the full sampled pool. - Frozen-opponent league: train the live policy against a pool of past exported checkpoints, sampled per-episode (today's
--opponent-mode=frozenonly supports one fixed model per run) to prevent self-play strategy collapse on long runs. - Richer state setter / curriculum: aerial states, wall plays, rebound scenarios as skill grows (beyond the score/defend/draw staging already in place).
- Main-menu difficulty picker: Easy/Medium/Hard presets in
main_menu.gdsetbot_model_path/bot_reaction_ticks/bot_action_noiseviaGameSettings. Raw-checkpoint testing and Spectate mode moved into aDevSectionhidden outside debug builds. All three tiers currently reusepromoted/easy.jsonwith different handicaps untilmedium/hardcheckpoints are promoted.
Multiplayer (long term)
RemoteShipController extends ShipController— feeds replicatedShipActions from a network peer into the local ship simulation.- Networked
GameModesubclass: per-peer ship spawning (MultiplayerSpawner or custom), authoritative server for ball/score. - C# backend / online servers per README roadmap (not started).
- Possible v0.2 split-screen: spawn one
ship_camera_rig+ viewport per local player (camera is already outside the ship scene to allow this).
General
- More arenas:
arena_02.tscn(Nebula) andarena_03.tscn(Asteroid Field) added alongsidearena_01.tscn, all following the same template (goals/spawns/arena_boundary.tscnunchanged) and listed inscripts/arena_registry.gd. Free Play lets the player pick an arena from the main menu; Match/Spectate each pick one at random per session; Training keeps its own fixedarena_01.tscnuntouched. - arena_02 (Nebula) redone RL-style:
arena_boundary.tscn's field material is now near-invisible glass (shared by all arenas), the sky is a baked photoreal-style equirect nebula texture (assets/textures/sky_nebula.png, procedurally generated offline — no copied astrophotography) instead of a procedural cell-shader, aNebulaDustGPUParticles3Dgives a drifting-motes "weather" effect, and theDecorationnode holds a station/debris/planet environment (Blender-modeled,assets/blender_models/nebula_decoration.blend→assets/models/nebula_*.glb) visible in multiple directions.arena_01/arena_03still use the older embedded-shader sky — same treatment for those is unstarted follow-up work.
Visual quality pass (arena_02 critique follow-up)
A subagent ran the game and critiqued arena_02 head-on against Rocket League 2 in Unreal Engine 5: verdict was "a flat-shaded, unlit-looking blockout dressed up with two nice noise textures" — not fundamentally unfixable in Godot (SDFGI/Nanite-tier GI and hero-sculpted geometry aside), but several concrete gaps. Work through these one at a time, in this order (cheapest/highest-impact first). Each item has a ready-to-use prompt — paste it into a fresh session to tackle just that piece. The texture-generation Python scripts used for sky_nebula.png/planet_surface.png currently only exist in an ephemeral scratchpad, not the repo — the first item that touches them should commit a copy into the repo (e.g. tools/textures/) so they're reproducible.
-
Post-processing pipeline (no models needed — cheapest, highest-impact item on the list). Nothing currently sits on top of the raw render: no bloom/glow, no AA, no color grading, no vignette beyond the floor's baked fade. Prompt: "In Cosmic Clash (Godot 4.7), the arena Environment resources (start with
Game/scenes/arena_02.tscn'sEnvironment_nebula, then apply consistently acrossarena_01/arena_03too) currently have no post-processing. Enable and tune Glow (bloom) so the nebula core, emissive accent strips on the station model, and bright stars actually bleed light; enable Adjustments (adjustment_enabled) for a subtle contrast/saturation grade. Godot'sEnvironmenthas no built-in vignette property — if that's still wanted, it needs a small custom full-screen shader (aCompositorEffector a screen-spaceColorRectoverlay), not a toggle; treat it as a separate, smaller sub-task rather than assuming it's free. Also enable FXAA and/or TAA viaproject.godot'srendering/anti_aliasing/quality/*settings project-wide to fix the aliased hard edges visible on ship geometry. Motion blur and depth-of-field are deliberately out of scope here — Godot has no built-in equivalent, and faking either well needs a customCompositorEffect, which is a much bigger task than this pass. Verify with before/after screenshots via godot-mcp (run_projectonfree_play.tscnwith the Nebula arena selected) — don't just eyeball the editor, actually run the game." -
De-duplicate the nebula sky's star sprites. Every bright star in
sky_nebula.pngis the exact same diffraction-spike stamp at the same size/brightness, just relocated — called out as "the single most amateur-looking tell in the whole scene" once you look for more than a second. Fixed: the generator is now committed attools/textures/gen_nebula_sky.py; the hero-star loop randomizes rotation, arm count (4 or 8), spike length, and brightness per star, andsky_nebula.pngwas regenerated/reimported and confirmed via in-game screenshot. Prompt: "Commit the nebula sky texture generator (currently only in an ephemeral scratchpad — recreate it if needed: numpy/Pillow script generating a 4096x2048 equirect nebula via layered FFT/domain-warped noise, color-graded, with drawn hero stars) into the repo attools/textures/gen_nebula_sky.py. Fix the hero-star drawing loop so each star's diffraction-spike stamp gets randomized rotation, spike length, and brightness instead of reusing one identical stamp at every location. RegenerateGame/assets/textures/sky_nebula.png, reimport, and confirm via an in-game screenshot that the repeated-stamp tell is gone." -
Real PBR lighting + materials, fresnel glass boundary (no new models — material/lighting setup only). Everything is flat-shaded/unshaded with a single directional light: no GI, no reflections, no bounce/AO, and the "glass" boundary is a flat unshaded tinted overlay with no fresnel rim or reflection. Prompt: "In Cosmic Clash, enable SDFGI and add reflection probes to the arena scenes (start with
arena_02.tscn) so surfaces get real bounce lighting/reflections instead of flat ambient. Convertarena_boundary.tscn'sStandardMaterial3D_fieldfrom unshaded to a proper shaded material with a fresnel-based rim highlight (bright at grazing angles, near-invisible face-on) so it reads as glass rather than a tinted overlay — check the performance impact of moving it off unshaded, given it's a large always-visible surface. Verify visually via godot-mcp screenshots, and confirm headless runs (free_play/match/spectate/training) still show zero errors." -
Greeble/detail pass on the station + debris models (Blender remodel — explicit models to redo).
nebula_station.glb/nebula_debris.glbare unmistakably Blender primitive kitbashes up close: plain boxes/cylinders with bevel modifiers, no panel lines, damage decals, or surface detail, and debris chunks look undifferentiated from the station. Prompt: "Using the blender MCP, rebuildnebula_station(source inGame/assets/blender_models/nebula_decoration.blend) with actual surface detail: greebled panel-line insets via bmesh inset-and-extrude on selected faces (more scriptable and robust than chained boolean cuts — prefer this over booleans for the main detailing pass), and 2-3 emissive window/light strips distinct from the existing single accent strip. A full normal-map/AO bake pipeline (low-poly + high-poly pair, UV unwrap, bake settings) is the ideal AAA-style finish but is fragile to script end-to-end in one pass — attempt it, but if it proves too unreliable, fall back to the inset/extrude geometric detail alone plus a simple tiled trim-sheet-style texture rather than forcing a bake that doesn't work. Givenebula_debrischunks a rockier/damaged material distinct from the station's clean hull (darker, rougher, maybe scorch-mark variation) so they read as separate debris rather than clones of the station's material. Re-export both toGame/assets/models/nebula_station.glb/nebula_debris.glb, re-save the shared.blend, and re-verify placement/transforms inarena_02.tscnstill look right (screenshot check)." -
Richer nebula sky + planet surface textures (extends the existing procedural generation — no new asset types).
sky_nebula.pngis essentially one noise-filter pass over a bright core;planet_surface.pngis a flat gradient with a single vortex swirl and no bands, craters, or day/night terminator. Prompt: "Extend the nebula/planet texture generators (seetools/textures/once committed, per the star-sprite TODO item above) with more detail layers: for the sky, add a second/third dust-lane layer at a different scale plus subtler color variation within the bright core (real nebulae aren't one flat color); for the planet, add a proper lit/unlit terminator gradient (the side facing the arena's directional light should read brighter), more band variation at different latitudes, and a couple more storm-vortex features so it doesn't read as a single gradient with one twist. Regenerate both textures, reimport, and screenshot-verify." -
Particle lighting response for the nebula dust ("weather") effect (no models — particle material/shader only). The
NebulaDustGPUParticles3Dmotes are generic soft glow sprites with no lighting interaction, no depth-based fade, and no secondary motion (no sparkle/color shift). Prompt: "Inarena_02.tscn'sNebulaDustparticle system, replace the current unshaded glow-sprite material with a custom shader that fakes lighting response — note the sprites are camera-facing billboards, so they have no fixed world-space normal and true per-pixel PBR lighting won't behave like it would on a solid mesh. A practical approach: derive a fake per-pixel normal from the quad's local UV (as if each sprite were a small sphere/puff, same trick used for 2D lit particle effects) and light that against the directional light + a fixed 'glow color' bias toward the nebula core direction, rather than relying on the mesh's real (camera-facing) normal. Add soft-particle depth fade (compare particle depth to the depth buffer) so motes don't hard-clip through the boundary/decoration geometry, and add subtle per-particle brightness flicker via the color ramp or shader for sparkle. Verify visually via godot-mcp screenshots that the dust reads as lit rather than flat-glowing, from a couple of different camera angles (billboard lighting tricks can look wrong from some angles even when right from others)." -
Ship + ball visual pass (Blender remodel — explicit models to make). The ship (
Game/objects/ship.tscn) is not a single placeholder box — it's already 5 separate primitiveMeshInstance3Dparts (HullaBoxMesh,NoseaPrismMesh,CanopyandEngineGlowboxes,TailFina thin box), several with emission already (the cyan canopy, the orangeEngineGlow, team-tintedNose/TailFin). It's the same underlying critique as everything else, though: plain primitives, no greebling/panel detail, no imported model — just built further already than the write-up above implied. Prompt: "Using the blender MCP, model an actual low-poly-but-detailed ship hull (greebled fuselage panel lines, a proper cockpit canopy shape, 1-2 engine nacelles with emissive exhaust glow) to replaceGame/objects/ship.tscn's current 5 primitiveMeshInstance3Dparts (Hull/Nose/Canopy/TailFin/EngineGlow), built the same procedural way as the arena decoration (bpy/bmesh primitives + bevels + inset/extrude detail — kept original, no borrowed/asset-store art). Two hard constraints this must respect: (1)scripts/ship.gd's_apply_team_color()recolors two child nodes by exact name,get_node_or_null(\"Nose\")andget_node_or_null(\"TailFin\"), at runtime per-team (team 0 blue, team 1 orange, set viagame_mode.gd'sship.team = team) — either keep twoMeshInstance3Dparts of the new model literally namedNoseandTailFinso this keeps working untouched, or update_apply_team_color()'s node-name list in the same change if the new model's parts are named differently; don't let this silently break. (2) Do not touchship.tscn's singleCollisionShape3D(BoxShape3D, size1 x 1 x 4) or theRigidBody3D'smass = 5.0/inertia = (1,1,1)/physics_material_override— those are exactly what the trained RL bots and flight feel are tuned against (per CLAUDE.md). Keep the new visual mesh's silhouette reasonably close to that1 x 1 x 4box so the ship doesn't visually stick out of or float inside its own collision bounds. Separately, audit the existing gold ball's material (Game/assets/models/gold_ball.glb/.res, referenced fromGame/objects/ball.tscn'sMeshInstance3Dwith no scene-level material override, so its look currently comes entirely from whatever's embedded in the imported mesh) and upgrade it to a proper metallic/emissive-accent PBR look if it turns out flat/unshaded once the lighting pass above lands — don't assume it needs work without checking first. Verify both visually (screenshot, including a look at team-color recoloring in Match/Spectate) and via a headless run offree_play.tscn/training.tscnto confirm physics/RL behavior is unaffected."