Move the ship & bullet systems into the object mod
This commit is contained in:
10
src/lib.rs
10
src/lib.rs
@@ -4,7 +4,6 @@ mod events;
|
|||||||
mod objects;
|
mod objects;
|
||||||
mod physics;
|
mod physics;
|
||||||
mod preparation_widget;
|
mod preparation_widget;
|
||||||
mod ship;
|
|
||||||
mod title_screen;
|
mod title_screen;
|
||||||
|
|
||||||
use crate::asteroids::AsteroidSpawner;
|
use crate::asteroids::AsteroidSpawner;
|
||||||
@@ -46,7 +45,10 @@ 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), (ship::spawn_player, spawn_ui))
|
.add_systems(
|
||||||
|
OnEnter(GameState::Playing),
|
||||||
|
(objects::spawn_player, spawn_ui),
|
||||||
|
)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
FixedUpdate,
|
FixedUpdate,
|
||||||
(
|
(
|
||||||
@@ -57,8 +59,8 @@ impl Plugin for AsteroidPlugin {
|
|||||||
asteroids::tick_asteroid_manager,
|
asteroids::tick_asteroid_manager,
|
||||||
objects::spawn_asteroid.after(asteroids::tick_asteroid_manager),
|
objects::spawn_asteroid.after(asteroids::tick_asteroid_manager),
|
||||||
objects::split_asteroids,
|
objects::split_asteroids,
|
||||||
ship::bullet_impact_listener,
|
objects::bullet_impact_listener,
|
||||||
ship::ship_impact_listener,
|
objects::ship_impact_listener,
|
||||||
collision_listener,
|
collision_listener,
|
||||||
// TODO: Remove debug printing
|
// TODO: Remove debug printing
|
||||||
debug_collision_event_printer,
|
debug_collision_event_printer,
|
||||||
|
|||||||
@@ -5,23 +5,26 @@
|
|||||||
use bevy::{
|
use bevy::{
|
||||||
ecs::{
|
ecs::{
|
||||||
component::Component,
|
component::Component,
|
||||||
|
entity::Entity,
|
||||||
event::{EventReader, EventWriter},
|
event::{EventReader, EventWriter},
|
||||||
system::{Commands, Query, Res},
|
query::With,
|
||||||
|
system::{Commands, Query, Res, ResMut, Single},
|
||||||
},
|
},
|
||||||
math::{Vec2, Vec3Swizzles},
|
math::{Vec2, Vec3, Vec3Swizzles},
|
||||||
prelude::{Deref, DerefMut},
|
prelude::{Deref, DerefMut},
|
||||||
render::mesh::Mesh2d,
|
render::mesh::Mesh2d,
|
||||||
sprite::MeshMaterial2d,
|
sprite::MeshMaterial2d,
|
||||||
|
state::state::NextState,
|
||||||
time::{Timer, TimerMode},
|
time::{Timer, TimerMode},
|
||||||
transform::components::Transform,
|
transform::components::Transform,
|
||||||
};
|
};
|
||||||
use bevy_rapier2d::prelude::{Collider, Sensor};
|
use bevy_rapier2d::prelude::{ActiveCollisionTypes, ActiveEvents, Collider, Sensor};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
GameAssets, Lifetime,
|
AngularVelocity, GameAssets, GameState, Lifetime, Lives,
|
||||||
config::ASTEROID_LIFETIME,
|
config::ASTEROID_LIFETIME,
|
||||||
events::{AsteroidDestroy, SpawnAsteroid},
|
events::{AsteroidDestroy, BulletDestroy, ShipDestroy, SpawnAsteroid},
|
||||||
physics::Velocity,
|
physics::{Velocity, Wrapping},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Component, Deref, DerefMut)]
|
#[derive(Component, Deref, DerefMut)]
|
||||||
@@ -121,3 +124,70 @@ pub fn split_asteroids(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
Velocity(Vec2::ZERO),
|
||||||
|
AngularVelocity(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)),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Watch for [`BulletDestroy`] events and despawn
|
||||||
|
/// the associated bullet.
|
||||||
|
pub fn bullet_impact_listener(mut commands: Commands, mut events: EventReader<BulletDestroy>) {
|
||||||
|
for event in events.read() {
|
||||||
|
commands.entity(event.0).despawn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Watch for [`ShipDestroy`] events and update game state accordingly.
|
||||||
|
///
|
||||||
|
/// - Subtract a life
|
||||||
|
/// - Check life count. If 0, go to game-over state
|
||||||
|
/// - Clear all asteroids
|
||||||
|
/// - Respawn player
|
||||||
|
pub fn ship_impact_listener(
|
||||||
|
mut events: EventReader<ShipDestroy>,
|
||||||
|
mut commands: Commands,
|
||||||
|
mut lives: ResMut<Lives>,
|
||||||
|
rocks: Query<Entity, With<Asteroid>>,
|
||||||
|
mut player: Single<(&mut Transform, &mut Velocity), With<Ship>>,
|
||||||
|
mut next_state: ResMut<NextState<GameState>>,
|
||||||
|
) {
|
||||||
|
for _ in events.read() {
|
||||||
|
// STEP 1: Decrement lives (and maybe go to game over)
|
||||||
|
if lives.0 == 0 {
|
||||||
|
// If already at 0, game is over.
|
||||||
|
next_state.set(GameState::GameOver);
|
||||||
|
} else {
|
||||||
|
// Decrease life count.
|
||||||
|
lives.0 -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// STEP 2: Clear asteroids
|
||||||
|
for rock in rocks {
|
||||||
|
commands.entity(rock).despawn();
|
||||||
|
}
|
||||||
|
|
||||||
|
// STEP 3: Respawn player (teleport them to the origin)
|
||||||
|
player.0.translation = Vec3::ZERO;
|
||||||
|
player.1.0 = Vec2::ZERO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
76
src/ship.rs
76
src/ship.rs
@@ -1,76 +0,0 @@
|
|||||||
use crate::{
|
|
||||||
AngularVelocity, GameAssets, GameState, Lives,
|
|
||||||
events::{BulletDestroy, ShipDestroy},
|
|
||||||
objects::{Asteroid, Ship},
|
|
||||||
physics::{Velocity, Wrapping},
|
|
||||||
};
|
|
||||||
|
|
||||||
use bevy::prelude::*;
|
|
||||||
use bevy_rapier2d::prelude::*;
|
|
||||||
|
|
||||||
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,
|
|
||||||
Velocity(Vec2::ZERO),
|
|
||||||
AngularVelocity(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)),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Watch for [`BulletDestroy`] events and despawn
|
|
||||||
/// the associated bullet.
|
|
||||||
pub fn bullet_impact_listener(mut commands: Commands, mut events: EventReader<BulletDestroy>) {
|
|
||||||
for event in events.read() {
|
|
||||||
commands.entity(event.0).despawn();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Watch for [`ShipDestroy`] events and update game state accordingly.
|
|
||||||
///
|
|
||||||
/// - Subtract a life
|
|
||||||
/// - Check life count. If 0, go to game-over state
|
|
||||||
/// - Clear all asteroids
|
|
||||||
/// - Respawn player
|
|
||||||
pub fn ship_impact_listener(
|
|
||||||
mut events: EventReader<ShipDestroy>,
|
|
||||||
mut commands: Commands,
|
|
||||||
mut lives: ResMut<Lives>,
|
|
||||||
rocks: Query<Entity, With<Asteroid>>,
|
|
||||||
mut player: Single<(&mut Transform, &mut Velocity), With<Ship>>,
|
|
||||||
mut next_state: ResMut<NextState<GameState>>,
|
|
||||||
) {
|
|
||||||
for _ in events.read() {
|
|
||||||
// STEP 1: Decrement lives (and maybe go to game over)
|
|
||||||
if lives.0 == 0 {
|
|
||||||
// If already at 0, game is over.
|
|
||||||
next_state.set(GameState::GameOver);
|
|
||||||
} else {
|
|
||||||
// Decrease life count.
|
|
||||||
lives.0 -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// STEP 2: Clear asteroids
|
|
||||||
for rock in rocks {
|
|
||||||
commands.entity(rock).despawn();
|
|
||||||
}
|
|
||||||
|
|
||||||
// STEP 3: Respawn player (teleport them to the origin)
|
|
||||||
player.0.translation = Vec3::ZERO;
|
|
||||||
player.1.0 = Vec2::ZERO;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user