From 809810b8ce5c5c815e72cee6a40f1f117c7025ee Mon Sep 17 00:00:00 2001 From: Robert Garrett Date: Sat, 9 Aug 2025 12:30:37 -0500 Subject: [PATCH] First parts of a collision event handler I've added a new `event` module to contain all the game's events (which it does not. I'll collect them all later). Using these events, the CollisionEvent listening system can watch for any two colliders intersecting, check on what role they play (asteroid, ship, bullet, etc), and re-emit an event for that specific thing. Each component can then handle it's own destruction process. --- src/event.rs | 14 +++++++++++++ src/lib.rs | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 src/event.rs diff --git a/src/event.rs b/src/event.rs new file mode 100644 index 0000000..40252d9 --- /dev/null +++ b/src/event.rs @@ -0,0 +1,14 @@ +use bevy::prelude::*; + +/// Signals that the player's ship has been destroyed. +/// Used when the player collides with an asteroid. +#[derive(Event)] +pub(crate) struct ShipDestroy; + +/// Signals that a particular asteroid has been destroyed. +/// Used to split (or vanish) an asteroid when a bullet strikes it. +#[derive(Event)] +pub(crate) struct AsteroidDestroy(pub Entity); + +// TODO: BulletDestroy +// Which depends on the still-pending Bullet component creation. diff --git a/src/lib.rs b/src/lib.rs index 01bf227..5f51fed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,12 +1,13 @@ mod asteroids; pub mod config; +mod event; mod preparation_widget; mod ship; mod title_screen; use crate::config::{BACKGROUND_COLOR, PLAYER_SHIP_COLOR, SHIP_ROTATION, SHIP_THRUST, WINDOW_SIZE}; -use asteroids::AsteroidSpawner; +use asteroids::{Asteroid, AsteroidSpawner}; use bevy::prelude::*; use bevy_inspector_egui::InspectorOptions; use bevy_inspector_egui::prelude::ReflectInspectorOptions; @@ -49,6 +50,7 @@ impl Plugin for AsteroidPlugin { wrap_entities, asteroids::tick_asteroid_manager, asteroids::spawn_asteroid.after(asteroids::tick_asteroid_manager), + collision_listener, // TODO: Remove debug printing debug_collision_event_printer, ) @@ -59,7 +61,9 @@ impl Plugin for AsteroidPlugin { (integrate_velocity, update_positions, apply_rotation_to_mesh) .run_if(in_state(GameState::Playing)), ) - .add_event::(); + .add_event::() + .add_event::() + .add_event::(); app.insert_state(GameState::TitleScreen); } } @@ -70,6 +74,54 @@ fn debug_collision_event_printer(mut collision_events: EventReader, + mut ship_writer: EventWriter, + mut asteroid_writer: EventWriter, + player: Single>, + rocks: Query<&Asteroid>, +) { + for event in collisions.read() { + if let CollisionEvent::Started(one, two, _flags) = event { + // Valid collisions are: + // + // - Ship & Asteroid + // - Bullet & Asteroid + // + // Asteroids don't collide with each other, bullets don't collide + // with each other, and bullets don't collide with the player ship. + + // Option 1: Ship & Asteroid + if *one == *player { + if rocks.contains(*two) { + // player-asteroid collision + dbg!("Writing ShipDestroy event"); + ship_writer.write(event::ShipDestroy); + } // else, we don't care + } else if *two == *player { + if rocks.contains(*one) { + dbg!("Writing ShipDestroy event"); + ship_writer.write(event::ShipDestroy); + } + } + + // TODO: Bullet-asteroid collisions + } + } +} + #[derive(Clone, Debug, Eq, Hash, PartialEq, States)] pub enum GameState { TitleScreen, // Program is started. Present title screen and await user start