use bevy::prelude::*; use rand::seq::{IndexedRandom, SliceRandom}; #[derive(Component)] pub struct Level { track: TrackPath, target_score: i32, } #[derive(Component)] pub struct LevelMarker; #[derive(Component)] pub struct DebugSlotNumber; #[derive(Resource)] pub struct TrackPath { pub points: Vec, pub spawn_index: usize, pub buffer_size: usize, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] pub enum BallType { #[default] First, Second, Third, Forth, } impl BallType { pub const fn asset_path(&self) -> &'static str { match self { BallType::First => "balls/1.png", BallType::Second => "balls/2.png", BallType::Third => "balls/3.png", BallType::Forth => "balls/4.png", } } pub fn random() -> Self { [Self::First, Self::Second, Self::Third, Self::Forth] .choose(&mut rand::rng()) .copied() .unwrap_or_default() } } #[derive(Component, Debug)] pub struct Ball { pub ball_type: BallType, pub slot_index: usize, pub slot_progress: f32, } #[derive(Resource)] pub struct SpawnTimer { pub timer: Timer, } impl Default for SpawnTimer { fn default() -> Self { Self { timer: Timer::from_seconds(2.0, TimerMode::Repeating), } } } #[derive(Resource)] pub struct WaveState { pub spawning_allowed: bool, pub ball_reached_end: bool, pub is_warming_up: bool, } impl Default for WaveState { fn default() -> Self { Self{ spawning_allowed: false, ball_reached_end: false, is_warming_up: false, } } } #[derive(Component)] pub struct WarmupTarget { pub target_index: usize, } #[derive(Component)] pub struct Cannon; #[derive(Component)] pub struct BallProjectile { pub velocity: Vec2, pub previous_position: Vec2, pub ball_type: BallType, }