Convert the flat TODO.md into a TODO/ folder where each GAL-N issue is
its own Linear-style markdown document with YAML frontmatter (id, title,
status, parent, labels), and add a README index grouped by section.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Every 3rd stage (3, 6, 9, ...) is now a special stage with no enemy
dive attacks and no enemy shooting. Enemies still spawn in the default
grid formation (32 enemies) but remain in formation without attacking.
Changes:
- Add SPECIAL_STAGE_INTERVAL constant and is_special_stage() function
- Add special_stage config to StageConfigurations with empty attack_patterns
- Modify for_stage() to route special stages to special config
- Guard enemy_shoot system to skip shooting during special stages
- Show '*' suffix in window title for special stages
Refs: GAL-39
Boss enemies now award 300 points instead of the same 100 as
Grunts. The scoring match in check_bullet_collisions already
routed by EnemyType; only the BOSS_POINTS constant was wrong.
Refs: GAL-27
Net -311 lines (1075 → 764). Build clean, clippy clean, 8 tests pass,
headless render verified.
Highlights:
- player.rs: bug fix in handle_captured_player — was cloning captured.timer
and ticking the clone, never the real timer. Consolidated kill_player as
pub(crate) helper (was duplicated across 3 sites). Switched from ParamSet
to two disjoint Queries.
- enemy.rs: extracted step_attacker(), spawn_beam_visual(), end_beam(),
pick_pattern() helpers — move_enemies is no longer 3-deep nested matches,
beam cleanup no longer duplicated. Fixed SwoopDive overshoot check (was
using already-applied movement). Mid-file `use` hoisted to top.
- resources.rs: added StageConfigurations::for_stage() helper (was repeated
4×); FormationState/Score/CurrentStage now Default; extracted
circle_formation() helper.
- stage.rs: replaced raw world: &mut World access with ordinary ResMut
system params (no need — resource types are disjoint).
- game_state.rs: cleanup queries collapsed via Or<…> filters; dropped dead
RestartMessage cleanup from cleanup_game_entities; button colors
extracted as constants.
- bullet.rs: reuses kill_player; introduced GRUNT_POINTS/BOSS_POINTS with
TODO referencing GAL-27.
- lib.rs: init_resource::<T>() for Default-implementing resources.
- Removed unused TRACTOR_BEAM_COLOR constant.
- Replaced per-frame println! debug spam with targeted info!/warn!.
- Stripped noise comments that restated what the code does.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Audit revealed Boss and Grunt both award 100 points (bullet.rs:48-51),
contradicting GAL-27's "different points" requirement. Added breakdown
sub-items to track what's done (colors, behaviors) vs. what's missing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Expose a `nix run .#take-screenshots` app that runs a binary inside an
Xvfb display with lavapipe software Vulkan and captures PNG snapshots
via ImageMagick. Useful for smoke-testing the Bevy renderer in
environments without a GPU (CI, sandboxed shells, agents).
Usage:
nix run .#take-screenshots -- EXE NUM DELAY_START PAUSE_INBETWEEN [OUTPUT_DIR]
The script picks the first free :N >= 99, locates the lavapipe ICD via
pkgs.mesa with a fallback to /run/opengl-driver (NixOS), reuses the
dev shell's runtimeLibs in LD_LIBRARY_PATH, and traps EXIT for cleanup.
README updated with usage and a worked example.
Move the App setup and module declarations from src/main.rs into a new
src/lib.rs that exposes a single pub fn run(). src/main.rs becomes a
three-line entry point that calls bglga::run(). This is the standard
Bevy-book pattern and lets the game logic be consumed as a library
(e.g. for integration tests, headless tooling, or alternate entry
points) without duplicating the App wiring.
Also gate update_tractor_beam_visual with
run_if(any_with_component::<TractorBeam>) so the system only runs while
a boss has an active tractor beam, instead of every Update tick.
Add Without<TractorBeamSprite> filter to boss_query so Bevy's parallel
access checker can prove the &Transform read on bosses and the
&mut Transform write on beam-sprite children target disjoint entity
sets. Without it, the system panicked on first run with a B0001
"conflicts with a previous system parameter" error.
Replace the single static rectangle with a 2-layer beam (outer glow +
inner core) and sinusoidal opacity pulse. Add per-frame beam height
tracking to follow boss position. Include 8 unit tests for pure math
functions (beam height calculation, pulse alpha).
Refs: GAL-33
Spawn expanding/fading orange explosion effects when enemies or
the player are destroyed. Explosions scale from 15x15 to 50x50
over 0.4s while fading from full opacity to transparent, then
auto-despawn.
Integration points:
- Enemy killed by player bullet (bullet.rs)
- Player hit by enemy bullet (bullet.rs)
- Player collides with enemy (player.rs) - both explode
- Captured player released (player.rs)
Refs: GAL-44
Add 150 stars with randomized positions, sizes, speeds, and brightness.
Stars scroll downward with parallax depth effect and wrap around at
screen edges. Also fixes Bevy 0.13 API issues in game_state.rs
(KeyCode::R → KeyR, Input → ButtonInput).
- Add StartMenu as the default game state
- Create StartMenuUI and StartButton components
- Implement menu UI with BGLGA title and Start Game button
- Add button interaction system with hover effects
- Set up proper state transitions from menu to game
- Update TODO.md to mark task as completed
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit introduces a new mechanic where boss enemies can use a tractor beam to capture the player.
Key changes:
- Bosses can now fire a tractor beam that targets the player.
- If the player is caught in the beam for a certain duration, they are "captured".
- Captured players are carried by the boss as it returns to its formation.
- If the boss is destroyed while carrying a player, the player is freed.
- If the player is captured, they lose a life and respawn.
- Refactored player and enemy systems to handle the new capture logic and states.
- Added GEMINI.md and CLAUDE.md to track assistant configurations.
- Introduce guidelines for writing commit messages.
- Emphasize the use of Conventional Commit format.
- Include tips for brevity and clarity in descriptions.
- Removed `std::time::Duration` import from `components.rs`, `resources.rs`, and `enemy.rs` as it was unnecessary.
- Cleaned up imports in `systems.rs` by removing `FormationState`.
Replaced direct buildInputs with LD_LIBRARY_PATH configuration to streamline dependency handling. This makes library paths explicitly managed and simplifies runtime linking for the required packages. Updated the devShells configuration accordingly.