diff --git a/src/asteroids.rs b/src/asteroids.rs index b2f5945..31562b1 100644 --- a/src/asteroids.rs +++ b/src/asteroids.rs @@ -7,17 +7,31 @@ use std::time::Duration; use bevy::prelude::*; -use crate::{GameAssets, Lifetime, WorldSize, config::ASTEROID_LIFETIME, physics::Velocity}; +use crate::{ + GameAssets, Lifetime, WorldSize, config::ASTEROID_LIFETIME, event::AsteroidDestroy, + physics::Velocity, +}; #[derive(Component, Deref, DerefMut)] pub struct Asteroid(AsteroidSize); +#[derive(Clone, Copy, Debug)] pub enum AsteroidSize { Small, Medium, Large, } +impl AsteroidSize { + fn next(&self) -> Option { + match self { + AsteroidSize::Small => None, + AsteroidSize::Medium => Some(AsteroidSize::Small), + AsteroidSize::Large => Some(AsteroidSize::Medium), + } + } +} + #[derive(Resource)] pub struct AsteroidSpawner { rng: std::sync::Mutex, @@ -128,3 +142,43 @@ pub fn spawn_asteroid( )); } } + +/// Event listener for asteroid destruction events. Shrinks and multiplies +/// asteroids until they vanish. +/// +/// - Large -> 2x Medium +/// - Medium -> 2x Small +/// - Small -> (despawned) +/// +/// The velocity of the child asteroids is scattered somewhat, as if they were +/// explosively pushed apart. +pub fn split_asteroids( + mut destroy_events: EventReader, + mut respawn_events: EventWriter, + mut commands: Commands, + query: Query<(&Transform, &Asteroid, &Velocity)>, +) { + for event in destroy_events.read() { + if let Ok((transform, rock, velocity)) = query.get(event.0) { + let next_size = rock.0.next(); + if let Some(size) = next_size { + let pos = transform.translation.xy(); + let left_offset = Vec2::from_angle(0.4); + let right_offset = Vec2::from_angle(-0.4); + respawn_events.write(SpawnAsteroid { + pos, + vel: left_offset.rotate(velocity.0), + size, + }); + respawn_events.write(SpawnAsteroid { + pos, + vel: right_offset.rotate(velocity.0), + size, + }); + } + // Always despawn the asteroid. New ones (may) be spawned in it's + // place, but this one is gone. + commands.entity(event.0).despawn(); + } + } +} diff --git a/src/lib.rs b/src/lib.rs index f287a64..b10a434 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -55,6 +55,7 @@ impl Plugin for AsteroidPlugin { physics::wrap_entities, asteroids::tick_asteroid_manager, asteroids::spawn_asteroid.after(asteroids::tick_asteroid_manager), + asteroids::split_asteroids, ship::bullet_impact_listener, collision_listener, // TODO: Remove debug printing