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
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>
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
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.
- 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`.