Compare commits
2 Commits
ab5f489450
...
809810b8ce
| Author | SHA1 | Date | |
|---|---|---|---|
| 809810b8ce | |||
| 29735e7426 |
14
src/event.rs
Normal file
14
src/event.rs
Normal file
@@ -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.
|
||||||
88
src/lib.rs
88
src/lib.rs
@@ -1,11 +1,13 @@
|
|||||||
mod asteroids;
|
mod asteroids;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
|
mod event;
|
||||||
mod preparation_widget;
|
mod preparation_widget;
|
||||||
|
mod ship;
|
||||||
mod title_screen;
|
mod title_screen;
|
||||||
|
|
||||||
use crate::config::{BACKGROUND_COLOR, PLAYER_SHIP_COLOR, SHIP_ROTATION, SHIP_THRUST, WINDOW_SIZE};
|
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::prelude::*;
|
||||||
use bevy_inspector_egui::InspectorOptions;
|
use bevy_inspector_egui::InspectorOptions;
|
||||||
use bevy_inspector_egui::prelude::ReflectInspectorOptions;
|
use bevy_inspector_egui::prelude::ReflectInspectorOptions;
|
||||||
@@ -16,6 +18,7 @@ use bevy_rapier2d::{
|
|||||||
render::RapierDebugRenderPlugin,
|
render::RapierDebugRenderPlugin,
|
||||||
};
|
};
|
||||||
use config::{ASTEROID_SMALL_COLOR, SHIP_THRUSTER_COLOR_ACTIVE, SHIP_THRUSTER_COLOR_INACTIVE};
|
use config::{ASTEROID_SMALL_COLOR, SHIP_THRUSTER_COLOR_ACTIVE, SHIP_THRUSTER_COLOR_INACTIVE};
|
||||||
|
use ship::Ship;
|
||||||
|
|
||||||
pub struct AsteroidPlugin;
|
pub struct AsteroidPlugin;
|
||||||
|
|
||||||
@@ -38,7 +41,7 @@ impl Plugin for AsteroidPlugin {
|
|||||||
.insert_resource(AsteroidSpawner::new())
|
.insert_resource(AsteroidSpawner::new())
|
||||||
.init_resource::<GameAssets>()
|
.init_resource::<GameAssets>()
|
||||||
.add_systems(Startup, spawn_camera)
|
.add_systems(Startup, spawn_camera)
|
||||||
.add_systems(OnEnter(GameState::Playing), (spawn_player, spawn_ui))
|
.add_systems(OnEnter(GameState::Playing), (ship::spawn_player, spawn_ui))
|
||||||
.add_systems(
|
.add_systems(
|
||||||
FixedUpdate,
|
FixedUpdate,
|
||||||
(
|
(
|
||||||
@@ -47,6 +50,7 @@ impl Plugin for AsteroidPlugin {
|
|||||||
wrap_entities,
|
wrap_entities,
|
||||||
asteroids::tick_asteroid_manager,
|
asteroids::tick_asteroid_manager,
|
||||||
asteroids::spawn_asteroid.after(asteroids::tick_asteroid_manager),
|
asteroids::spawn_asteroid.after(asteroids::tick_asteroid_manager),
|
||||||
|
collision_listener,
|
||||||
// TODO: Remove debug printing
|
// TODO: Remove debug printing
|
||||||
debug_collision_event_printer,
|
debug_collision_event_printer,
|
||||||
)
|
)
|
||||||
@@ -57,7 +61,9 @@ impl Plugin for AsteroidPlugin {
|
|||||||
(integrate_velocity, update_positions, apply_rotation_to_mesh)
|
(integrate_velocity, update_positions, apply_rotation_to_mesh)
|
||||||
.run_if(in_state(GameState::Playing)),
|
.run_if(in_state(GameState::Playing)),
|
||||||
)
|
)
|
||||||
.add_event::<asteroids::SpawnAsteroid>();
|
.add_event::<asteroids::SpawnAsteroid>()
|
||||||
|
.add_event::<event::AsteroidDestroy>()
|
||||||
|
.add_event::<event::ShipDestroy>();
|
||||||
app.insert_state(GameState::TitleScreen);
|
app.insert_state(GameState::TitleScreen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,6 +74,54 @@ fn debug_collision_event_printer(mut collision_events: EventReader<CollisionEven
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The collision event routing system.
|
||||||
|
///
|
||||||
|
/// When a `CollisionEvent` occurrs, this system checks which things collided
|
||||||
|
/// and emits secondary events accordignly.
|
||||||
|
///
|
||||||
|
/// | Objects | Response |
|
||||||
|
/// |-|-|
|
||||||
|
/// | Ship & Asteroid | emits event [`ShipDestroy`](`crate::event::ShipDestroy`) |
|
||||||
|
/// | Asteroid & Bullet | emits event [`AsteroidDestroy`](`crate::event::AsteroidDestroy`) |
|
||||||
|
/// | Asteroid & Asteroid | Nothing. Asteroids won't collide with each other |
|
||||||
|
/// | Bullet & Bullet | Nothing. Bullets won't collide with each other (and probably can't under normal gameplay conditions) |
|
||||||
|
/// | Bullet & Ship | Nothing. The player shouldn't be able to shoot themselves (and the Flying Saucer hasn't been impl.'d, so it's bullets don't count) |
|
||||||
|
fn collision_listener(
|
||||||
|
mut collisions: EventReader<CollisionEvent>,
|
||||||
|
mut ship_writer: EventWriter<event::ShipDestroy>,
|
||||||
|
mut asteroid_writer: EventWriter<event::AsteroidDestroy>,
|
||||||
|
player: Single<Entity, With<Ship>>,
|
||||||
|
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)]
|
#[derive(Clone, Debug, Eq, Hash, PartialEq, States)]
|
||||||
pub enum GameState {
|
pub enum GameState {
|
||||||
TitleScreen, // Program is started. Present title screen and await user start
|
TitleScreen, // Program is started. Present title screen and await user start
|
||||||
@@ -85,9 +139,6 @@ struct Velocity(bevy::math::Vec2);
|
|||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
struct Rotation(f32);
|
struct Rotation(f32);
|
||||||
|
|
||||||
#[derive(Component)]
|
|
||||||
struct Ship;
|
|
||||||
|
|
||||||
/// Marker for any entity that should wrap on screen edges
|
/// Marker for any entity that should wrap on screen edges
|
||||||
#[derive(Component)]
|
#[derive(Component)]
|
||||||
struct Wrapping;
|
struct Wrapping;
|
||||||
@@ -188,31 +239,6 @@ fn spawn_camera(mut commands: Commands) {
|
|||||||
commands.spawn(Camera2d);
|
commands.spawn(Camera2d);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawn_player(mut commands: Commands, game_assets: Res<GameAssets>) {
|
|
||||||
commands
|
|
||||||
.spawn((
|
|
||||||
Collider::ball(0.7),
|
|
||||||
Sensor,
|
|
||||||
ActiveEvents::COLLISION_EVENTS,
|
|
||||||
ActiveCollisionTypes::STATIC_STATIC,
|
|
||||||
Ship,
|
|
||||||
Wrapping,
|
|
||||||
Position(Vec2::default()),
|
|
||||||
Velocity(Vec2::ZERO),
|
|
||||||
Rotation(0.0),
|
|
||||||
Mesh2d(game_assets.ship().0),
|
|
||||||
MeshMaterial2d(game_assets.ship().1),
|
|
||||||
Transform::default().with_scale(Vec3::new(20.0, 20.0, 20.0)),
|
|
||||||
))
|
|
||||||
.with_child((
|
|
||||||
Mesh2d(game_assets.thruster_mesh()),
|
|
||||||
MeshMaterial2d(game_assets.thruster_mat_inactive()),
|
|
||||||
Transform::default()
|
|
||||||
.with_scale(Vec3::splat(0.5))
|
|
||||||
.with_translation(Vec3::new(-0.5, 0.0, -0.1)),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Checks if "W" is pressed and increases velocity accordingly.
|
Checks if "W" is pressed and increases velocity accordingly.
|
||||||
*/
|
*/
|
||||||
|
|||||||
32
src/ship.rs
Normal file
32
src/ship.rs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
use bevy::prelude::*;
|
||||||
|
use bevy_rapier2d::prelude::*;
|
||||||
|
|
||||||
|
use crate::{GameAssets, Position, Rotation, Velocity, Wrapping};
|
||||||
|
|
||||||
|
#[derive(Component)]
|
||||||
|
pub struct Ship;
|
||||||
|
|
||||||
|
pub fn spawn_player(mut commands: Commands, game_assets: Res<GameAssets>) {
|
||||||
|
commands
|
||||||
|
.spawn((
|
||||||
|
Collider::ball(0.7),
|
||||||
|
Sensor,
|
||||||
|
ActiveEvents::COLLISION_EVENTS,
|
||||||
|
ActiveCollisionTypes::STATIC_STATIC,
|
||||||
|
Ship,
|
||||||
|
Wrapping,
|
||||||
|
Position(Vec2::default()),
|
||||||
|
Velocity(Vec2::ZERO),
|
||||||
|
Rotation(0.0),
|
||||||
|
Mesh2d(game_assets.ship().0),
|
||||||
|
MeshMaterial2d(game_assets.ship().1),
|
||||||
|
Transform::default().with_scale(Vec3::new(20.0, 20.0, 20.0)),
|
||||||
|
))
|
||||||
|
.with_child((
|
||||||
|
Mesh2d(game_assets.thruster_mesh()),
|
||||||
|
MeshMaterial2d(game_assets.thruster_mat_inactive()),
|
||||||
|
Transform::default()
|
||||||
|
.with_scale(Vec3::splat(0.5))
|
||||||
|
.with_translation(Vec3::new(-0.5, 0.0, -0.1)),
|
||||||
|
));
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user