bglga/src/lib.rs
Harald Hoyer b2b564f690 chore(deps): upgrade Bevy 0.13 → 0.18
Three major versions of breaking changes:
- Bundles → Required Components (SpriteBundle, NodeBundle, ButtonBundle,
  TextBundle, Camera2dBundle removed; spawn tuples of components instead)
- Style merged into Node; TextStyle split into TextFont + TextColor
- Color API: rgb/rgba → srgb/srgba; Color::Rgba pattern matching replaced
  with .alpha()/.set_alpha(); .r()/.g()/.b() → .to_srgba().red/green/blue
- Time: delta_seconds() → delta_secs(); elapsed_seconds() → elapsed_secs()
- Query: get_single()/get_single_mut() → single()/single_mut() (now Result)
- Timer::finished() → Timer::is_finished()
- despawn_recursive() removed (despawn() is now recursive); despawn_descendants()
  removed — replaced with Children query iteration
- BorderColor(c) → BorderColor::all(c)
- WindowResolution: From<(f32,f32)> removed → cast to (u32,u32)
- flake.nix: added wayland to runtime libs (default-on in 0.18)

Tests pass (8/8), clippy clean, headless render verified showing start
menu, button, starfield, and player ship.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-06 21:26:48 +02:00

127 lines
4.7 KiB
Rust

#![allow(clippy::type_complexity)]
use bevy::prelude::*;
use std::time::Duration;
pub mod components;
pub mod constants;
pub mod resources;
pub mod game_state;
pub mod player;
pub mod enemy;
pub mod bullet;
pub mod stage;
pub mod systems;
pub mod starfield;
use components::TractorBeam;
use constants::{PLAYER_RESPAWN_DELAY, STARTING_LIVES, WINDOW_HEIGHT, WINDOW_WIDTH};
use resources::{
AttackDiveTimer, CurrentStage, EnemySpawnTimer, FormationState, PlayerLives,
PlayerRespawnTimer, Score, StageConfigurations,
};
use game_state::{
cleanup_game_entities, cleanup_game_over_ui, setup_game_over_ui, AppState,
setup_start_menu_ui, cleanup_start_menu_ui, start_menu_button_system,
handle_restart_input, restart_game_system,
};
use resources::RestartPressed;
use player::{
check_player_enemy_collisions, manage_invincibility, move_player, player_shoot,
respawn_player, handle_captured_player,
};
use enemy::{
check_formation_complete, enemy_shoot, is_formation_complete, move_enemies, spawn_enemies,
trigger_attack_dives, boss_capture_attack, update_tractor_beam_visual,
};
use bullet::{
check_bullet_collisions, check_enemy_bullet_player_collisions, move_bullets,
move_enemy_bullets,
};
use stage::check_stage_clear;
use systems::{player_exists, player_vulnerable, setup, should_respawn_player, update_window_title, animate_explosion};
use starfield::scroll_starfield;
pub fn run() {
App::new()
.insert_resource(ClearColor(Color::srgb(0.0, 0.0, 0.1)))
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "BGLGA".into(),
resolution: (WINDOW_WIDTH as u32, WINDOW_HEIGHT as u32).into(),
resizable: false,
..default()
}),
..default()
}))
.init_state::<AppState>()
.insert_resource(EnemySpawnTimer {
timer: Timer::new(Duration::from_secs_f32(1.0), TimerMode::Once),
})
.insert_resource(PlayerLives { count: STARTING_LIVES })
.insert_resource(PlayerRespawnTimer {
timer: Timer::new(
Duration::from_secs_f32(PLAYER_RESPAWN_DELAY),
TimerMode::Once,
),
})
.insert_resource(Score { value: 0 })
.insert_resource(CurrentStage {
number: 1,
waiting_for_clear: false,
})
.insert_resource(FormationState {
formation_complete: false,
total_spawned_this_stage: 0,
next_slot_index: 0,
})
.insert_resource(AttackDiveTimer {
timer: Timer::new(Duration::from_secs_f32(3.0), TimerMode::Once),
})
.insert_resource(StageConfigurations::default())
.insert_resource(RestartPressed::default())
.add_systems(Startup, setup)
.add_systems(
Update,
(
update_window_title,
spawn_enemies,
move_player.run_if(player_exists),
player_shoot.run_if(player_exists),
check_player_enemy_collisions.run_if(player_vulnerable),
respawn_player.run_if(should_respawn_player),
manage_invincibility,
handle_captured_player,
move_bullets,
check_bullet_collisions,
move_enemy_bullets,
check_enemy_bullet_player_collisions.run_if(player_vulnerable),
move_enemies,
enemy_shoot,
boss_capture_attack,
update_tractor_beam_visual.run_if(any_with_component::<TractorBeam>),
)
.run_if(in_state(AppState::Playing)),
)
.add_systems(
Update,
(
check_formation_complete,
trigger_attack_dives.run_if(is_formation_complete),
check_stage_clear,
)
.chain()
.run_if(in_state(AppState::Playing)),
)
.add_systems(Update, scroll_starfield)
.add_systems(Update, animate_explosion)
.add_systems(OnEnter(AppState::StartMenu), setup_start_menu_ui)
.add_systems(OnExit(AppState::StartMenu), cleanup_start_menu_ui)
.add_systems(Update, start_menu_button_system.run_if(in_state(AppState::StartMenu)))
.add_systems(OnEnter(AppState::GameOver), setup_game_over_ui)
.add_systems(Update, handle_restart_input.run_if(in_state(AppState::GameOver)))
.add_systems(Update, restart_game_system.run_if(in_state(AppState::GameOver)))
.add_systems(OnExit(AppState::Playing), cleanup_game_entities)
.add_systems(OnExit(AppState::GameOver), cleanup_game_over_ui)
.run();
}