mirror of
https://github.com/kristoferssolo/maze-ascension.git
synced 2025-10-21 19:20:34 +00:00
refactor: move to [observer](https://bevyengine.org/examples/ecs-entity-component-system/observers/) based systems
This commit is contained in:
parent
e65790c743
commit
cec07c9069
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -3083,7 +3083,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "maze-ascension"
|
name = "maze-ascension"
|
||||||
version = "0.2.0"
|
version = "0.2.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bevy",
|
"bevy",
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "maze-ascension"
|
name = "maze-ascension"
|
||||||
authors = ["Kristofers Solo <dev@kristofers.xyz>"]
|
authors = ["Kristofers Solo <dev@kristofers.xyz>"]
|
||||||
version = "0.2.0"
|
version = "0.2.2"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
floor::components::{CurrentFloor, Floor},
|
floor::components::{CurrentFloor, Floor},
|
||||||
maze::{components::MazeConfig, events::MazeEvent, GlobalMazeConfig, MazePluginLoaded},
|
maze::{components::MazeConfig, events::RespawnMaze, GlobalMazeConfig, MazePluginLoaded},
|
||||||
player::events::PlayerEvent,
|
player::events::RespawnPlayer,
|
||||||
};
|
};
|
||||||
use bevy::{prelude::*, window::PrimaryWindow};
|
use bevy::{prelude::*, window::PrimaryWindow};
|
||||||
use bevy_egui::{
|
use bevy_egui::{
|
||||||
@ -58,16 +58,11 @@ pub(crate) fn maze_controls_ui(world: &mut World) {
|
|||||||
// Handle updates
|
// Handle updates
|
||||||
if changed {
|
if changed {
|
||||||
maze_config.update(&global_config);
|
maze_config.update(&global_config);
|
||||||
|
world.trigger(RespawnMaze {
|
||||||
if let Some(mut event_writer) = world.get_resource_mut::<Events<MazeEvent>>() {
|
floor: floor_value,
|
||||||
event_writer.send(MazeEvent::Recreate {
|
config: maze_config,
|
||||||
floor: floor_value,
|
});
|
||||||
config: maze_config,
|
world.trigger(RespawnPlayer);
|
||||||
});
|
|
||||||
}
|
|
||||||
if let Some(mut event_writer) = world.get_resource_mut::<Events<PlayerEvent>>() {
|
|
||||||
event_writer.send(PlayerEvent::Respawn);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
20
src/floor/events.rs
Normal file
20
src/floor/events.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
use crate::maze::components::MazeConfig;
|
||||||
|
|
||||||
|
#[derive(Debug, Reflect, Event)]
|
||||||
|
pub struct SpawnFloor {
|
||||||
|
pub floor: u8,
|
||||||
|
pub config: MazeConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Reflect, Event)]
|
||||||
|
pub struct RespawnFloor {
|
||||||
|
pub floor: u8,
|
||||||
|
pub config: MazeConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Reflect, Event)]
|
||||||
|
pub struct DespawnFloor {
|
||||||
|
pub floor: u8,
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
pub mod components;
|
pub mod components;
|
||||||
|
pub mod events;
|
||||||
mod systems;
|
mod systems;
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
pub(super) fn plugin(app: &mut App) {}
|
pub(super) fn plugin(_app: &mut App) {}
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
mod spawn;
|
|
||||||
|
|||||||
@ -62,6 +62,7 @@ impl Plugin for AppPlugin {
|
|||||||
screens::plugin,
|
screens::plugin,
|
||||||
theme::plugin,
|
theme::plugin,
|
||||||
maze::plugin,
|
maze::plugin,
|
||||||
|
floor::plugin,
|
||||||
player::plugin,
|
player::plugin,
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|||||||
@ -2,9 +2,19 @@ use bevy::prelude::*;
|
|||||||
|
|
||||||
use super::components::MazeConfig;
|
use super::components::MazeConfig;
|
||||||
|
|
||||||
#[derive(Debug, Event)]
|
#[derive(Debug, Reflect, Event)]
|
||||||
pub enum MazeEvent {
|
pub struct SpawnMaze {
|
||||||
Create { floor: u8, config: MazeConfig },
|
pub floor: u8,
|
||||||
Recreate { floor: u8, config: MazeConfig },
|
pub config: MazeConfig,
|
||||||
Remove { floor: u8 },
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Reflect, Event)]
|
||||||
|
pub struct RespawnMaze {
|
||||||
|
pub floor: u8,
|
||||||
|
pub config: MazeConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Reflect, Event)]
|
||||||
|
pub struct DespawnMaze {
|
||||||
|
pub floor: u8,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,17 +4,20 @@ pub mod errors;
|
|||||||
pub mod events;
|
pub mod events;
|
||||||
pub mod resources;
|
pub mod resources;
|
||||||
mod systems;
|
mod systems;
|
||||||
|
mod triggers;
|
||||||
|
|
||||||
use bevy::{ecs::system::RunSystemOnce, prelude::*};
|
use bevy::{ecs::system::RunSystemOnce, prelude::*};
|
||||||
use components::Maze;
|
use components::Maze;
|
||||||
use events::MazeEvent;
|
use events::{DespawnMaze, RespawnMaze, SpawnMaze};
|
||||||
pub use resources::{GlobalMazeConfig, MazePluginLoaded};
|
pub use resources::{GlobalMazeConfig, MazePluginLoaded};
|
||||||
|
|
||||||
pub(super) fn plugin(app: &mut App) {
|
pub(super) fn plugin(app: &mut App) {
|
||||||
app.init_resource::<GlobalMazeConfig>()
|
app.init_resource::<GlobalMazeConfig>()
|
||||||
.add_event::<MazeEvent>()
|
.add_event::<SpawnMaze>()
|
||||||
|
.add_event::<RespawnMaze>()
|
||||||
|
.add_event::<DespawnMaze>()
|
||||||
.register_type::<Maze>()
|
.register_type::<Maze>()
|
||||||
.add_plugins(systems::plugin);
|
.add_plugins((systems::plugin, triggers::plugin));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spawn_level_command(world: &mut World) {
|
pub fn spawn_level_command(world: &mut World) {
|
||||||
|
|||||||
@ -1,54 +0,0 @@
|
|||||||
use super::{spawn::spawn_floor, update::update_floor};
|
|
||||||
use crate::{
|
|
||||||
floor::components::Floor,
|
|
||||||
maze::{components::Maze, events::MazeEvent, GlobalMazeConfig},
|
|
||||||
};
|
|
||||||
use bevy::prelude::*;
|
|
||||||
|
|
||||||
pub(crate) fn handle_maze_events(
|
|
||||||
mut commands: Commands,
|
|
||||||
mut meshes: ResMut<Assets<Mesh>>,
|
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
|
||||||
mut event_reader: EventReader<MazeEvent>,
|
|
||||||
mut maze_query: Query<(Entity, &Floor, &mut Maze)>,
|
|
||||||
global_config: Res<GlobalMazeConfig>,
|
|
||||||
) {
|
|
||||||
for event in event_reader.read() {
|
|
||||||
match event {
|
|
||||||
MazeEvent::Create { floor, config } => {
|
|
||||||
if maze_query.iter().any(|(_, f, _)| f.0 == *floor) {
|
|
||||||
warn!("Floor {} already exists, skipping creation", floor);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
spawn_floor(
|
|
||||||
&mut commands,
|
|
||||||
&mut meshes,
|
|
||||||
&mut materials,
|
|
||||||
*floor,
|
|
||||||
config,
|
|
||||||
&global_config,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
MazeEvent::Recreate { floor, config } => {
|
|
||||||
let result = update_floor(
|
|
||||||
&mut commands,
|
|
||||||
&mut meshes,
|
|
||||||
&mut materials,
|
|
||||||
&mut maze_query,
|
|
||||||
*floor,
|
|
||||||
config,
|
|
||||||
&global_config,
|
|
||||||
);
|
|
||||||
if let Err(e) = result {
|
|
||||||
warn!("Failed to update floor {}: {}", floor, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MazeEvent::Remove { floor } => {
|
|
||||||
match maze_query.iter().find(|(_, f, _)| f.0 == *floor) {
|
|
||||||
Some((entity, _, _)) => commands.entity(entity).despawn_recursive(),
|
|
||||||
_ => warn!("Floor {} not found for removal", floor),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,12 +1,5 @@
|
|||||||
pub mod common;
|
|
||||||
pub mod event_handler;
|
|
||||||
pub mod setup;
|
pub mod setup;
|
||||||
pub mod spawn;
|
|
||||||
pub mod update;
|
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use event_handler::handle_maze_events;
|
|
||||||
|
|
||||||
pub(super) fn plugin(app: &mut App) {
|
pub(super) fn plugin(_app: &mut App) {}
|
||||||
app.add_systems(Update, handle_maze_events);
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use crate::maze::{components::MazeConfig, events::MazeEvent};
|
use crate::maze::{components::MazeConfig, events::SpawnMaze};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
pub(crate) fn setup(mut event_writer: EventWriter<MazeEvent>) {
|
pub(crate) fn setup(mut commands: Commands) {
|
||||||
let config = MazeConfig::default();
|
let config = MazeConfig::default();
|
||||||
event_writer.send(MazeEvent::Create { floor: 1, config });
|
commands.trigger(SpawnMaze { floor: 1, config });
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,43 +0,0 @@
|
|||||||
use super::{common::generate_maze, spawn::spawn_maze_tiles};
|
|
||||||
use crate::{
|
|
||||||
floor::components::Floor,
|
|
||||||
maze::{
|
|
||||||
assets::MazeAssets,
|
|
||||||
components::{Maze, MazeConfig},
|
|
||||||
errors::{MazeError, MazeResult},
|
|
||||||
GlobalMazeConfig,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
use bevy::prelude::*;
|
|
||||||
|
|
||||||
pub(super) fn update_floor(
|
|
||||||
commands: &mut Commands,
|
|
||||||
meshes: &mut ResMut<Assets<Mesh>>,
|
|
||||||
materials: &mut ResMut<Assets<StandardMaterial>>,
|
|
||||||
maze_query: &mut Query<(Entity, &Floor, &mut Maze)>,
|
|
||||||
floor: u8,
|
|
||||||
maze_config: &MazeConfig,
|
|
||||||
global_config: &GlobalMazeConfig,
|
|
||||||
) -> MazeResult<()> {
|
|
||||||
let (entity, _, mut maze) = maze_query
|
|
||||||
.iter_mut()
|
|
||||||
.find(|(_, f, _)| f.0 == floor)
|
|
||||||
.ok_or(MazeError::FloorNotFound(floor))?;
|
|
||||||
|
|
||||||
maze.0 = generate_maze(maze_config)?;
|
|
||||||
|
|
||||||
commands.entity(entity).despawn_descendants();
|
|
||||||
let assets = MazeAssets::new(meshes, materials, global_config);
|
|
||||||
spawn_maze_tiles(
|
|
||||||
commands,
|
|
||||||
entity,
|
|
||||||
&maze.0,
|
|
||||||
&assets,
|
|
||||||
maze_config,
|
|
||||||
global_config,
|
|
||||||
);
|
|
||||||
|
|
||||||
commands.entity(entity).insert(maze_config.clone());
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
@ -4,7 +4,7 @@ use crate::maze::{
|
|||||||
};
|
};
|
||||||
use hexlab::{GeneratorType, HexMaze, MazeBuilder};
|
use hexlab::{GeneratorType, HexMaze, MazeBuilder};
|
||||||
|
|
||||||
pub(super) fn generate_maze(config: &MazeConfig) -> MazeResult<HexMaze> {
|
pub(crate) fn generate_maze(config: &MazeConfig) -> MazeResult<HexMaze> {
|
||||||
MazeBuilder::new()
|
MazeBuilder::new()
|
||||||
.with_radius(config.radius)
|
.with_radius(config.radius)
|
||||||
.with_seed(config.seed)
|
.with_seed(config.seed)
|
||||||
14
src/maze/triggers/despawn.rs
Normal file
14
src/maze/triggers/despawn.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
use crate::{floor::components::Floor, maze::events::DespawnMaze};
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
pub(super) fn despawn_maze(
|
||||||
|
trigger: Trigger<DespawnMaze>,
|
||||||
|
mut commands: Commands,
|
||||||
|
query: Query<(Entity, &Floor)>,
|
||||||
|
) {
|
||||||
|
let DespawnMaze { floor } = trigger.event();
|
||||||
|
match query.iter().find(|(_, f)| f.0 == *floor) {
|
||||||
|
Some((entity, _)) => commands.entity(entity).despawn_recursive(),
|
||||||
|
_ => warn!("Floor {} not found for removal", floor),
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/maze/triggers/mod.rs
Normal file
15
src/maze/triggers/mod.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
pub mod common;
|
||||||
|
mod despawn;
|
||||||
|
mod respawn;
|
||||||
|
mod spawn;
|
||||||
|
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use despawn::despawn_maze;
|
||||||
|
use respawn::respawn_maze;
|
||||||
|
use spawn::spawn_maze;
|
||||||
|
|
||||||
|
pub(super) fn plugin(app: &mut App) {
|
||||||
|
app.add_observer(spawn_maze)
|
||||||
|
.add_observer(respawn_maze)
|
||||||
|
.add_observer(despawn_maze);
|
||||||
|
}
|
||||||
53
src/maze/triggers/respawn.rs
Normal file
53
src/maze/triggers/respawn.rs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
use super::{common::generate_maze, spawn::spawn_maze_tiles};
|
||||||
|
use crate::{
|
||||||
|
floor::components::Floor,
|
||||||
|
maze::{
|
||||||
|
assets::MazeAssets, components::Maze, errors::MazeError, events::RespawnMaze,
|
||||||
|
GlobalMazeConfig,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
pub(super) fn respawn_maze(
|
||||||
|
trigger: Trigger<RespawnMaze>,
|
||||||
|
mut commands: Commands,
|
||||||
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
|
mut maze_query: Query<(Entity, &Floor, &mut Maze)>,
|
||||||
|
global_config: Res<GlobalMazeConfig>,
|
||||||
|
) {
|
||||||
|
let RespawnMaze { floor, config } = trigger.event();
|
||||||
|
|
||||||
|
let (entity, _, mut maze) = match maze_query
|
||||||
|
.iter_mut()
|
||||||
|
.find(|(_, f, _)| f.0 == *floor)
|
||||||
|
.ok_or(MazeError::FloorNotFound(*floor))
|
||||||
|
{
|
||||||
|
Ok((entity, floor, maze)) => (entity, floor, maze),
|
||||||
|
Err(e) => {
|
||||||
|
warn!("Failed to update floor ({floor}). {e}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
maze.0 = match generate_maze(config) {
|
||||||
|
Ok(generated_maze) => generated_maze,
|
||||||
|
Err(e) => {
|
||||||
|
warn!("Failed to update floor ({floor}). {e}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
commands.entity(entity).despawn_descendants();
|
||||||
|
let assets = MazeAssets::new(&mut meshes, &mut materials, &global_config);
|
||||||
|
spawn_maze_tiles(
|
||||||
|
&mut commands,
|
||||||
|
entity,
|
||||||
|
&maze.0,
|
||||||
|
&assets,
|
||||||
|
config,
|
||||||
|
&global_config,
|
||||||
|
);
|
||||||
|
|
||||||
|
commands.entity(entity).insert(config.clone());
|
||||||
|
}
|
||||||
@ -3,6 +3,7 @@ use crate::{
|
|||||||
maze::{
|
maze::{
|
||||||
assets::MazeAssets,
|
assets::MazeAssets,
|
||||||
components::{Maze, MazeConfig, Tile, Wall},
|
components::{Maze, MazeConfig, Tile, Wall},
|
||||||
|
events::SpawnMaze,
|
||||||
resources::GlobalMazeConfig,
|
resources::GlobalMazeConfig,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -13,30 +14,43 @@ use std::f32::consts::{FRAC_PI_2, FRAC_PI_3, FRAC_PI_6};
|
|||||||
|
|
||||||
use super::common::generate_maze;
|
use super::common::generate_maze;
|
||||||
|
|
||||||
pub(super) fn spawn_floor(
|
pub(super) fn spawn_maze(
|
||||||
commands: &mut Commands,
|
trigger: Trigger<SpawnMaze>,
|
||||||
meshes: &mut ResMut<Assets<Mesh>>,
|
mut commands: Commands,
|
||||||
materials: &mut ResMut<Assets<StandardMaterial>>,
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
floor: u8,
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
maze_config: &MazeConfig,
|
maze_query: Query<(Entity, &Floor, &Maze)>,
|
||||||
global_config: &GlobalMazeConfig,
|
global_config: Res<GlobalMazeConfig>,
|
||||||
) {
|
) {
|
||||||
let maze = generate_maze(maze_config).expect("Failed to generate maze during spawn");
|
let SpawnMaze { floor, config } = trigger.event();
|
||||||
|
if maze_query.iter().any(|(_, f, _)| f.0 == *floor) {
|
||||||
|
warn!("Floor {} already exists, skipping creation", floor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let maze = generate_maze(config).expect("Failed to generate maze during spawn");
|
||||||
|
|
||||||
let entity = commands
|
let entity = commands
|
||||||
.spawn((
|
.spawn((
|
||||||
Name::new(format!("Floor {}", floor)),
|
Name::new(format!("Floor {}", floor)),
|
||||||
Maze(maze.clone()),
|
Maze(maze.clone()),
|
||||||
Floor(floor),
|
Floor(*floor),
|
||||||
CurrentFloor, // TODO: remove
|
CurrentFloor, // TODO: remove
|
||||||
maze_config.clone(),
|
config.clone(),
|
||||||
Transform::from_translation(Vec3::ZERO),
|
Transform::from_translation(Vec3::ZERO),
|
||||||
Visibility::Visible,
|
Visibility::Visible,
|
||||||
))
|
))
|
||||||
.id();
|
.id();
|
||||||
|
|
||||||
let assets = MazeAssets::new(meshes, materials, global_config);
|
let assets = MazeAssets::new(&mut meshes, &mut materials, &global_config);
|
||||||
spawn_maze_tiles(commands, entity, &maze, &assets, maze_config, global_config);
|
spawn_maze_tiles(
|
||||||
|
&mut commands,
|
||||||
|
entity,
|
||||||
|
&maze,
|
||||||
|
&assets,
|
||||||
|
config,
|
||||||
|
&global_config,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn spawn_maze_tiles(
|
pub(super) fn spawn_maze_tiles(
|
||||||
@ -1,8 +1,10 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
#[derive(Debug, Event)]
|
#[derive(Debug, Event)]
|
||||||
pub enum PlayerEvent {
|
pub struct SpawnPlayer;
|
||||||
Spawn,
|
|
||||||
Respawn,
|
#[derive(Debug, Event)]
|
||||||
Despawn,
|
pub struct RespawnPlayer;
|
||||||
}
|
|
||||||
|
#[derive(Debug, Event)]
|
||||||
|
pub struct DespawnPlayer;
|
||||||
|
|||||||
@ -2,15 +2,18 @@ mod assets;
|
|||||||
pub mod components;
|
pub mod components;
|
||||||
pub mod events;
|
pub mod events;
|
||||||
mod systems;
|
mod systems;
|
||||||
|
mod triggers;
|
||||||
|
|
||||||
use bevy::{ecs::system::RunSystemOnce, prelude::*};
|
use bevy::{ecs::system::RunSystemOnce, prelude::*};
|
||||||
use components::Player;
|
use components::Player;
|
||||||
use events::PlayerEvent;
|
use events::{DespawnPlayer, RespawnPlayer, SpawnPlayer};
|
||||||
|
|
||||||
pub(super) fn plugin(app: &mut App) {
|
pub(super) fn plugin(app: &mut App) {
|
||||||
app.register_type::<Player>()
|
app.register_type::<Player>()
|
||||||
.add_event::<PlayerEvent>()
|
.add_event::<SpawnPlayer>()
|
||||||
.add_plugins(systems::plugin);
|
.add_event::<RespawnPlayer>()
|
||||||
|
.add_event::<DespawnPlayer>()
|
||||||
|
.add_plugins((triggers::plugin, systems::plugin));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spawn_player_command(world: &mut World) {
|
pub fn spawn_player_command(world: &mut World) {
|
||||||
|
|||||||
@ -1,9 +0,0 @@
|
|||||||
use bevy::prelude::*;
|
|
||||||
|
|
||||||
use crate::player::components::Player;
|
|
||||||
|
|
||||||
pub(super) fn despawn_players(commands: &mut Commands, query: &Query<Entity, With<Player>>) {
|
|
||||||
for entity in query.iter() {
|
|
||||||
commands.entity(entity).despawn_recursive();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,53 +0,0 @@
|
|||||||
use crate::{
|
|
||||||
floor::components::CurrentFloor,
|
|
||||||
maze::{components::MazeConfig, GlobalMazeConfig},
|
|
||||||
player::{components::Player, events::PlayerEvent},
|
|
||||||
};
|
|
||||||
use bevy::prelude::*;
|
|
||||||
|
|
||||||
use super::{despawn::despawn_players, respawn::respawn_player, spawn::spawn_player};
|
|
||||||
|
|
||||||
pub(crate) fn handle_player_events(
|
|
||||||
mut commands: Commands,
|
|
||||||
mut meshes: ResMut<Assets<Mesh>>,
|
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>,
|
|
||||||
mut event_reader: EventReader<PlayerEvent>,
|
|
||||||
maze_config_query: Query<&MazeConfig, With<CurrentFloor>>,
|
|
||||||
player_query: Query<Entity, With<Player>>,
|
|
||||||
global_config: Res<GlobalMazeConfig>,
|
|
||||||
) {
|
|
||||||
for event in event_reader.read() {
|
|
||||||
match event {
|
|
||||||
PlayerEvent::Spawn => {
|
|
||||||
let Ok(maze_config) = maze_config_query.get_single() else {
|
|
||||||
warn!(
|
|
||||||
"Failed to get maze configuration for current floor - cannot spawn player"
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
spawn_player(
|
|
||||||
&mut commands,
|
|
||||||
&mut meshes,
|
|
||||||
&mut materials,
|
|
||||||
maze_config,
|
|
||||||
&global_config,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
PlayerEvent::Respawn => {
|
|
||||||
let Ok(maze_config) = maze_config_query.get_single() else {
|
|
||||||
warn!("Failed to get maze configuration for current floor - cannot respawn player");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
respawn_player(
|
|
||||||
&mut commands,
|
|
||||||
&mut meshes,
|
|
||||||
&mut materials,
|
|
||||||
&player_query,
|
|
||||||
maze_config,
|
|
||||||
&global_config,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
PlayerEvent::Despawn => despawn_players(&mut commands, &player_query),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,23 +1,18 @@
|
|||||||
mod despawn;
|
|
||||||
mod event_handler;
|
|
||||||
mod input;
|
mod input;
|
||||||
mod movement;
|
mod movement;
|
||||||
mod respawn;
|
|
||||||
pub mod setup;
|
pub mod setup;
|
||||||
mod spawn;
|
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use event_handler::handle_player_events;
|
|
||||||
use input::player_input;
|
use input::player_input;
|
||||||
use movement::player_movement;
|
use movement::player_movement;
|
||||||
|
|
||||||
|
use crate::maze::MazePluginLoaded;
|
||||||
|
|
||||||
pub(super) fn plugin(app: &mut App) {
|
pub(super) fn plugin(app: &mut App) {
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
Update,
|
Update,
|
||||||
(
|
(player_input, player_movement)
|
||||||
player_input,
|
.chain()
|
||||||
player_movement.after(player_input),
|
.run_if(resource_exists::<MazePluginLoaded>),
|
||||||
handle_player_events,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,18 +0,0 @@
|
|||||||
use super::{despawn::despawn_players, spawn::spawn_player};
|
|
||||||
use crate::{
|
|
||||||
maze::{components::MazeConfig, GlobalMazeConfig},
|
|
||||||
player::components::Player,
|
|
||||||
};
|
|
||||||
use bevy::prelude::*;
|
|
||||||
|
|
||||||
pub(super) fn respawn_player(
|
|
||||||
commands: &mut Commands,
|
|
||||||
meshes: &mut ResMut<Assets<Mesh>>,
|
|
||||||
materials: &mut ResMut<Assets<StandardMaterial>>,
|
|
||||||
query: &Query<Entity, With<Player>>,
|
|
||||||
maze_config: &MazeConfig,
|
|
||||||
global_config: &GlobalMazeConfig,
|
|
||||||
) {
|
|
||||||
despawn_players(commands, query);
|
|
||||||
spawn_player(commands, meshes, materials, maze_config, global_config);
|
|
||||||
}
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::player::events::PlayerEvent;
|
use crate::player::events::SpawnPlayer;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
pub(crate) fn setup(mut event_writer: EventWriter<PlayerEvent>) {
|
pub(crate) fn setup(mut commands: Commands) {
|
||||||
event_writer.send(PlayerEvent::Spawn);
|
commands.trigger(SpawnPlayer);
|
||||||
}
|
}
|
||||||
|
|||||||
12
src/player/triggers/despawn.rs
Normal file
12
src/player/triggers/despawn.rs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
use crate::player::{components::Player, events::DespawnPlayer};
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
pub(super) fn despawn_players(
|
||||||
|
_trigger: Trigger<DespawnPlayer>,
|
||||||
|
mut commands: Commands,
|
||||||
|
query: Query<Entity, With<Player>>,
|
||||||
|
) {
|
||||||
|
for entity in query.iter() {
|
||||||
|
commands.entity(entity).despawn_recursive();
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/player/triggers/mod.rs
Normal file
14
src/player/triggers/mod.rs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
mod despawn;
|
||||||
|
mod respawn;
|
||||||
|
mod spawn;
|
||||||
|
|
||||||
|
use bevy::prelude::*;
|
||||||
|
use despawn::despawn_players;
|
||||||
|
use respawn::respawn_player;
|
||||||
|
use spawn::spawn_player;
|
||||||
|
|
||||||
|
pub(super) fn plugin(app: &mut App) {
|
||||||
|
app.add_observer(spawn_player)
|
||||||
|
.add_observer(respawn_player)
|
||||||
|
.add_observer(despawn_players);
|
||||||
|
}
|
||||||
7
src/player/triggers/respawn.rs
Normal file
7
src/player/triggers/respawn.rs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
use crate::player::events::{DespawnPlayer, RespawnPlayer, SpawnPlayer};
|
||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
pub(super) fn respawn_player(_trigger: Trigger<RespawnPlayer>, mut commands: Commands) {
|
||||||
|
commands.trigger(DespawnPlayer);
|
||||||
|
commands.trigger(SpawnPlayer);
|
||||||
|
}
|
||||||
@ -1,19 +1,25 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
|
floor::components::CurrentFloor,
|
||||||
maze::{components::MazeConfig, GlobalMazeConfig},
|
maze::{components::MazeConfig, GlobalMazeConfig},
|
||||||
player::{
|
player::{
|
||||||
assets::{blue_material, generate_pill_mesh},
|
assets::{blue_material, generate_pill_mesh},
|
||||||
components::{CurrentPosition, Player},
|
components::{CurrentPosition, Player},
|
||||||
|
events::SpawnPlayer,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
pub(super) fn spawn_player(
|
pub(super) fn spawn_player(
|
||||||
commands: &mut Commands,
|
_trigger: Trigger<SpawnPlayer>,
|
||||||
meshes: &mut ResMut<Assets<Mesh>>,
|
mut commands: Commands,
|
||||||
materials: &mut ResMut<Assets<StandardMaterial>>,
|
mut meshes: ResMut<Assets<Mesh>>,
|
||||||
maze_config: &MazeConfig,
|
mut materials: ResMut<Assets<StandardMaterial>>,
|
||||||
global_config: &GlobalMazeConfig,
|
maze_config_query: Query<&MazeConfig, With<CurrentFloor>>,
|
||||||
|
global_config: Res<GlobalMazeConfig>,
|
||||||
) {
|
) {
|
||||||
|
let Ok(maze_config) = maze_config_query.get_single() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
let player_radius = global_config.hex_size * 0.5;
|
let player_radius = global_config.hex_size * 0.5;
|
||||||
let player_height = player_radius * 3.5;
|
let player_height = player_radius * 3.5;
|
||||||
|
|
||||||
@ -9,10 +9,7 @@ use crate::{asset_tracking::LoadResource, audio::Music, screens::Screen};
|
|||||||
pub(super) fn plugin(app: &mut App) {
|
pub(super) fn plugin(app: &mut App) {
|
||||||
app.add_systems(
|
app.add_systems(
|
||||||
OnEnter(Screen::Gameplay),
|
OnEnter(Screen::Gameplay),
|
||||||
(
|
(spawn_level_command, spawn_player_command).chain(),
|
||||||
spawn_level_command,
|
|
||||||
spawn_player_command.after(spawn_level_command),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
app.load_resource::<GameplayMusic>();
|
app.load_resource::<GameplayMusic>();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user