refactor: idiomatic cleanup across the codebase

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>
This commit is contained in:
Harald Hoyer 2026-05-06 21:36:26 +02:00
parent b2b564f690
commit ad2037a7a5
11 changed files with 762 additions and 1073 deletions

View file

@ -1,8 +1,8 @@
use crate::components::{Bullet, Enemy, GameOverUI, RestartMessage, StartButton, StartMenuUI};
use crate::resources::RestartPressed;
use bevy::prelude::*;
// --- Game States ---
use crate::components::{Bullet, Enemy, EnemyBullet, GameOverUI, RestartMessage, StartButton, StartMenuUI};
use crate::resources::RestartPressed;
#[derive(Clone, Eq, PartialEq, Debug, Hash, Default, States)]
pub enum AppState {
#[default]
@ -11,10 +11,12 @@ pub enum AppState {
GameOver,
}
const BUTTON_IDLE: Color = Color::srgb(0.1, 0.1, 0.5);
const BUTTON_HOVER: Color = Color::srgb(0.2, 0.2, 0.7);
// --- Game Over UI ---
pub fn setup_game_over_ui(mut commands: Commands) {
println!("Entering GameOver state. Setting up UI.");
commands.spawn((
Text::new("GAME OVER"),
TextFont {
@ -51,39 +53,20 @@ pub fn setup_game_over_ui(mut commands: Commands) {
pub fn cleanup_game_over_ui(
mut commands: Commands,
query: Query<Entity, With<GameOverUI>>,
restart_query: Query<Entity, With<RestartMessage>>,
query: Query<Entity, Or<(With<GameOverUI>, With<RestartMessage>)>>,
) {
println!("Exiting GameOver state. Cleaning up UI.");
for entity in query.iter() {
commands.entity(entity).despawn();
}
for entity in restart_query.iter() {
for entity in &query {
commands.entity(entity).despawn();
}
}
// --- Cleanup ---
// --- Cleanup on leaving Playing ---
// Cleanup system when exiting the Playing state
pub fn cleanup_game_entities(
mut commands: Commands,
bullet_query: Query<Entity, With<Bullet>>,
enemy_bullet_query: Query<Entity, With<crate::components::EnemyBullet>>,
enemy_query: Query<Entity, With<Enemy>>,
restart_message_query: Query<Entity, With<crate::components::RestartMessage>>,
query: Query<Entity, Or<(With<Bullet>, With<EnemyBullet>, With<Enemy>)>>,
) {
println!("Exiting Playing state. Cleaning up game entities.");
for entity in bullet_query.iter() {
commands.entity(entity).despawn();
}
for entity in enemy_bullet_query.iter() {
commands.entity(entity).despawn();
}
for entity in enemy_query.iter() {
commands.entity(entity).despawn();
}
for entity in restart_message_query.iter() {
for entity in &query {
commands.entity(entity).despawn();
}
}
@ -91,8 +74,6 @@ pub fn cleanup_game_entities(
// --- Start Menu UI ---
pub fn setup_start_menu_ui(mut commands: Commands) {
println!("Entering StartMenu state. Setting up UI.");
commands
.spawn((
Node {
@ -106,7 +87,6 @@ pub fn setup_start_menu_ui(mut commands: Commands) {
StartMenuUI,
))
.with_children(|parent| {
// Title
parent.spawn((
Text::new("BGLGA"),
TextFont {
@ -119,8 +99,6 @@ pub fn setup_start_menu_ui(mut commands: Commands) {
..default()
},
));
// Start Game Button
parent
.spawn((
Button,
@ -133,7 +111,7 @@ pub fn setup_start_menu_ui(mut commands: Commands) {
..default()
},
BorderColor::all(Color::WHITE),
BackgroundColor(Color::srgb(0.1, 0.1, 0.5)),
BackgroundColor(BUTTON_IDLE),
StartButton,
))
.with_children(|parent| {
@ -150,51 +128,42 @@ pub fn setup_start_menu_ui(mut commands: Commands) {
}
pub fn cleanup_start_menu_ui(mut commands: Commands, query: Query<Entity, With<StartMenuUI>>) {
println!("Exiting StartMenu state. Cleaning up UI.");
for entity in query.iter() {
for entity in &query {
commands.entity(entity).despawn();
}
}
pub fn start_menu_button_system(
mut interaction_query: Query<
mut interactions: Query<
(&Interaction, &mut BackgroundColor),
(Changed<Interaction>, With<StartButton>),
>,
mut app_state: ResMut<NextState<AppState>>,
mut next_state: ResMut<NextState<AppState>>,
) {
for (interaction, mut color) in &mut interaction_query {
for (interaction, mut bg) in &mut interactions {
match *interaction {
Interaction::Pressed => {
println!("Start button pressed! Transitioning to Playing state.");
app_state.set(AppState::Playing);
}
Interaction::Hovered => {
color.0 = Color::srgb(0.2, 0.2, 0.7);
}
Interaction::None => {
color.0 = Color::srgb(0.1, 0.1, 0.5);
}
Interaction::Pressed => next_state.set(AppState::Playing),
Interaction::Hovered => bg.0 = BUTTON_HOVER,
Interaction::None => bg.0 = BUTTON_IDLE,
}
}
}
pub fn handle_restart_input(
keyboard_input: Res<ButtonInput<KeyCode>>,
mut restart_resource: ResMut<RestartPressed>,
keyboard: Res<ButtonInput<KeyCode>>,
mut restart: ResMut<RestartPressed>,
) {
if keyboard_input.just_pressed(KeyCode::KeyR) {
restart_resource.pressed = true;
if keyboard.just_pressed(KeyCode::KeyR) {
restart.pressed = true;
}
}
pub fn restart_game_system(
mut app_state: ResMut<NextState<AppState>>,
mut restart_resource: ResMut<RestartPressed>,
mut next_state: ResMut<NextState<AppState>>,
mut restart: ResMut<RestartPressed>,
) {
if restart_resource.pressed {
println!("Restart requested. Transitioning to Playing state.");
restart_resource.pressed = false;
app_state.set(AppState::Playing);
if restart.pressed {
restart.pressed = false;
next_state.set(AppState::Playing);
}
}