From 269686323ff77edbde182306733471172f31ef37 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Wed, 18 Dec 2024 17:01:21 +0200 Subject: [PATCH 01/16] feat(player): add ascension/descension --- src/floor/components.rs | 14 ++++++++++++-- src/floor/mod.rs | 4 +++- src/floor/systems/mod.rs | 2 ++ src/maze/assets.rs | 28 +++++++++++++++++++++++++--- src/maze/triggers/spawn.rs | 18 +++++++++++++++++- src/player/events.rs | 10 ++++++++++ src/player/mod.rs | 4 +++- src/player/systems/ascend.rs | 30 ++++++++++++++++++++++++++++++ src/player/systems/descend.rs | 30 ++++++++++++++++++++++++++++++ src/player/systems/mod.rs | 9 ++++++--- 10 files changed, 138 insertions(+), 11 deletions(-) create mode 100644 src/player/systems/ascend.rs create mode 100644 src/player/systems/descend.rs diff --git a/src/floor/components.rs b/src/floor/components.rs index de73815..7f421d4 100644 --- a/src/floor/components.rs +++ b/src/floor/components.rs @@ -1,10 +1,10 @@ use bevy::prelude::*; -#[derive(Debug, Reflect, Component)] +#[derive(Debug, Reflect, Component, Deref, DerefMut)] #[reflect(Component)] pub struct Floor(pub u8); -#[derive(Debug, Reflect, Component)] +#[derive(Debug, Reflect, Component, Deref, DerefMut)] #[reflect(Component)] pub struct TargetFloor(pub u8); @@ -17,3 +17,13 @@ impl Default for Floor { Self(1) } } + +impl Floor { + pub fn increase(&self) -> Self { + Self(self.0.saturating_add(1)) + } + + pub fn decrease(&self) -> Self { + Self(self.0.saturating_sub(1).max(1)) + } +} diff --git a/src/floor/mod.rs b/src/floor/mod.rs index b071bcf..b0e8bc0 100644 --- a/src/floor/mod.rs +++ b/src/floor/mod.rs @@ -4,4 +4,6 @@ mod systems; use bevy::prelude::*; -pub(super) fn plugin(_app: &mut App) {} +pub(super) fn plugin(app: &mut App) { + app.add_plugins(systems::plugin); +} diff --git a/src/floor/systems/mod.rs b/src/floor/systems/mod.rs index 8b13789..5b1303d 100644 --- a/src/floor/systems/mod.rs +++ b/src/floor/systems/mod.rs @@ -1 +1,3 @@ +use bevy::prelude::*; +pub(super) fn plugin(_app: &mut App) {} diff --git a/src/maze/assets.rs b/src/maze/assets.rs index 011d406..12d9872 100644 --- a/src/maze/assets.rs +++ b/src/maze/assets.rs @@ -1,5 +1,7 @@ +use crate::theme::palette::rose_pine::{LOVE, PINE}; + use super::resources::GlobalMazeConfig; -use bevy::prelude::*; +use bevy::{prelude::*, utils::HashMap}; use std::f32::consts::FRAC_PI_2; const WALL_OVERLAP_MODIFIER: f32 = 1.25; @@ -11,6 +13,7 @@ pub(crate) struct MazeAssets { pub(crate) wall_mesh: Handle, pub(crate) hex_material: Handle, pub(crate) wall_material: Handle, + pub(crate) custom_materials: HashMap>, } impl MazeAssets { @@ -19,6 +22,11 @@ impl MazeAssets { materials: &mut ResMut>, global_config: &GlobalMazeConfig, ) -> MazeAssets { + let mut custom_materials = HashMap::new(); + custom_materials.extend(vec![ + ("LOVE".to_string(), materials.add(red_material())), + ("PINE".to_string(), materials.add(blue_material())), + ]); MazeAssets { hex_mesh: meshes.add(generate_hex_mesh( global_config.hex_size, @@ -30,6 +38,7 @@ impl MazeAssets { )), hex_material: materials.add(white_material()), wall_material: materials.add(Color::BLACK), + custom_materials, } } } @@ -53,9 +62,8 @@ fn generate_square_mesh(depth: f32, wall_size: f32) -> Mesh { Mesh::from(rectangular_prism).rotated_by(rotation) } -fn white_material() -> StandardMaterial { +pub(crate) fn white_material() -> StandardMaterial { StandardMaterial { - base_color: Color::WHITE, emissive: LinearRgba::new( WHITE_EMISSION_INTENSITY, WHITE_EMISSION_INTENSITY, @@ -65,3 +73,17 @@ fn white_material() -> StandardMaterial { ..default() } } + +pub(crate) fn red_material() -> StandardMaterial { + StandardMaterial { + emissive: LOVE.to_linear(), + ..default() + } +} + +pub(crate) fn blue_material() -> StandardMaterial { + StandardMaterial { + emissive: PINE.to_linear(), + ..default() + } +} diff --git a/src/maze/triggers/spawn.rs b/src/maze/triggers/spawn.rs index af25d4a..e7ed398 100644 --- a/src/maze/triggers/spawn.rs +++ b/src/maze/triggers/spawn.rs @@ -81,12 +81,28 @@ pub(super) fn spawn_single_hex_tile( HexOrientation::Flat => Quat::from_rotation_y(FRAC_PI_6), // 30 degrees rotation }; + let material = match tile.pos() { + pos if pos == maze_config.start_pos => assets + .custom_materials + .get("PINE") + .cloned() + .to_owned() + .unwrap(), + pos if pos == maze_config.end_pos => assets + .custom_materials + .get("LOVE") + .cloned() + .to_owned() + .unwrap(), + _ => assets.hex_material.clone(), + }; + parent .spawn(( Name::new(format!("Hex {}", tile)), Tile, Mesh3d(assets.hex_mesh.clone()), - MeshMaterial3d(assets.hex_material.clone()), + MeshMaterial3d(material), Transform::from_translation(world_pos).with_rotation(rotation), )) .with_children(|parent| spawn_walls(parent, assets, tile.walls(), global_config)); diff --git a/src/player/events.rs b/src/player/events.rs index 953c8c9..04ed340 100644 --- a/src/player/events.rs +++ b/src/player/events.rs @@ -8,3 +8,13 @@ pub struct RespawnPlayer; #[derive(Debug, Event)] pub struct DespawnPlayer; + +#[derive(Debug, Event)] +pub struct AscendPlayer { + pub floor: u8, +} + +#[derive(Debug, Event)] +pub struct DescendPlayer { + pub floor: u8, +} diff --git a/src/player/mod.rs b/src/player/mod.rs index 480168d..624c110 100644 --- a/src/player/mod.rs +++ b/src/player/mod.rs @@ -6,13 +6,15 @@ mod triggers; use bevy::{ecs::system::RunSystemOnce, prelude::*}; use components::Player; -use events::{DespawnPlayer, RespawnPlayer, SpawnPlayer}; +use events::{AscendPlayer, DescendPlayer, DespawnPlayer, RespawnPlayer, SpawnPlayer}; pub(super) fn plugin(app: &mut App) { app.register_type::() .add_event::() .add_event::() .add_event::() + .add_event::() + .add_event::() .add_plugins((triggers::plugin, systems::plugin)); } diff --git a/src/player/systems/ascend.rs b/src/player/systems/ascend.rs new file mode 100644 index 0000000..c20f01a --- /dev/null +++ b/src/player/systems/ascend.rs @@ -0,0 +1,30 @@ +use bevy::prelude::*; + +use crate::{ + floor::components::{CurrentFloor, Floor}, + maze::components::MazeConfig, + player::{ + components::{CurrentPosition, Player}, + events::AscendPlayer, + }, +}; + +pub(super) fn ascend_player( + query: Query<&CurrentPosition, With>, + maze_config_query: Query<(&MazeConfig, &Floor), With>, + mut event_writer: EventWriter, +) { + let Ok((config, floor)) = maze_config_query.get_single() else { + warn!("No current floor configuration found"); + return; + }; + + for current_hex in query.iter() { + if current_hex.0 == config.end_pos { + event_writer.send(AscendPlayer { + floor: *floor.increase(), + }); + return; + } + } +} diff --git a/src/player/systems/descend.rs b/src/player/systems/descend.rs new file mode 100644 index 0000000..d03b67e --- /dev/null +++ b/src/player/systems/descend.rs @@ -0,0 +1,30 @@ +use bevy::prelude::*; + +use crate::{ + floor::components::{CurrentFloor, Floor}, + maze::components::MazeConfig, + player::{ + components::{CurrentPosition, Player}, + events::DescendPlayer, + }, +}; + +pub(super) fn descend_player( + query: Query<&CurrentPosition, With>, + maze_config_query: Query<(&MazeConfig, &Floor), With>, + mut event_writer: EventWriter, +) { + let Ok((config, floor)) = maze_config_query.get_single() else { + warn!("No current floor configuration found"); + return; + }; + + for current_hex in query.iter() { + if current_hex.0 == config.start_pos { + event_writer.send(DescendPlayer { + floor: *floor.decrease(), + }); + return; + } + } +} diff --git a/src/player/systems/mod.rs b/src/player/systems/mod.rs index 7d69b84..df081cd 100644 --- a/src/player/systems/mod.rs +++ b/src/player/systems/mod.rs @@ -1,17 +1,20 @@ +mod ascend; +mod descend; mod input; mod movement; pub mod setup; +use crate::maze::MazePluginLoaded; +use ascend::ascend_player; use bevy::prelude::*; +use descend::descend_player; use input::player_input; use movement::player_movement; -use crate::maze::MazePluginLoaded; - pub(super) fn plugin(app: &mut App) { app.add_systems( Update, - (player_input, player_movement) + (player_input, player_movement, ascend_player, descend_player) .chain() .run_if(resource_exists::), ); From de4989ccfbce4a74f68014287d58832c9ea14a59 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Wed, 18 Dec 2024 17:11:02 +0200 Subject: [PATCH 02/16] test(floor): add min/max tests --- Cargo.lock | 166 ++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 6 ++ src/floor/components.rs | 30 +++++++- 3 files changed, 198 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index efe3c3f..bd6bacb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2299,6 +2299,21 @@ dependencies = [ "libc", ] +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.31" @@ -2306,6 +2321,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -2314,6 +2330,17 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + [[package]] name = "futures-io" version = "0.3.31" @@ -2333,6 +2360,53 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + [[package]] name = "fuzzy-matcher" version = "0.3.7" @@ -3093,6 +3167,9 @@ dependencies = [ "hexx", "log", "rand", + "rstest", + "rstest_reuse", + "test-log", "thiserror 2.0.6", "tracing", ] @@ -3749,6 +3826,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "piper" version = "0.2.4" @@ -4032,6 +4115,12 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +[[package]] +name = "relative-path" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" + [[package]] name = "renderdoc-sys" version = "1.1.0" @@ -4067,12 +4156,62 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97" +[[package]] +name = "rstest" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a2c585be59b6b5dd66a9d2084aa1d8bd52fbdb806eafdeffb52791147862035" +dependencies = [ + "futures", + "futures-timer", + "rstest_macros", + "rustc_version", +] + +[[package]] +name = "rstest_macros" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "825ea780781b15345a146be27eaefb05085e337e869bff01b4306a4fd4a9ad5a" +dependencies = [ + "cfg-if", + "glob", + "proc-macro-crate", + "proc-macro2", + "quote", + "regex", + "relative-path", + "rustc_version", + "syn", + "unicode-ident", +] + +[[package]] +name = "rstest_reuse" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3a8fb4672e840a587a66fc577a5491375df51ddb88f2a2c2a792598c326fe14" +dependencies = [ + "quote", + "rand", + "syn", +] + [[package]] name = "rustc-hash" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "0.38.42" @@ -4158,6 +4297,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2fdfc24bc566f839a2da4c4295b82db7d25a24253867d5c64355abb5799bdbe" +[[package]] +name = "semver" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" + [[package]] name = "send_wrapper" version = "0.6.0" @@ -4401,6 +4546,27 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "test-log" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dffced63c2b5c7be278154d76b479f9f9920ed34e7574201407f0b14e2bbb93" +dependencies = [ + "test-log-macros", + "tracing-subscriber", +] + +[[package]] +name = "test-log-macros" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5999e24eaa32083191ba4e425deb75cdf25efefabe5aaccb7446dd0d4122a3f5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "thiserror" version = "1.0.69" diff --git a/Cargo.toml b/Cargo.toml index ed2c0c4..44b271b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,12 @@ bevy_egui = { version = "0.31", optional = true } thiserror = "2.0" anyhow = "1" +[dev-dependencies] +rstest = "0.23" +rstest_reuse = "0.7" +test-log = { version = "0.2.16", default-features = false, features = [ + "trace", +] } [features] default = [ diff --git a/src/floor/components.rs b/src/floor/components.rs index 7f421d4..a44f17b 100644 --- a/src/floor/components.rs +++ b/src/floor/components.rs @@ -4,10 +4,6 @@ use bevy::prelude::*; #[reflect(Component)] pub struct Floor(pub u8); -#[derive(Debug, Reflect, Component, Deref, DerefMut)] -#[reflect(Component)] -pub struct TargetFloor(pub u8); - #[derive(Debug, Reflect, Component)] #[reflect(Component)] pub struct CurrentFloor; @@ -27,3 +23,29 @@ impl Floor { Self(self.0.saturating_sub(1).max(1)) } } + +#[cfg(test)] +mod tests { + use super::*; + use rstest::rstest; + + #[rstest] + #[case(0, 1)] + #[case(1, 2)] + #[case(254, 255)] + #[case(255, 255)] + fn increase(#[case] input: u8, #[case] expected: u8) { + let floor = Floor(input); + assert_eq!(*floor.increase(), expected); + } + + #[rstest] + #[case(0, 1)] // clamps to 1 + #[case(1, 1)] // clamps to 1 + #[case(2, 1)] + #[case(255, 254)] + fn decrease(#[case] input: u8, #[case] expected: u8) { + let floor = Floor(input); + assert_eq!(*floor.decrease(), expected); + } +} From 86bbee8cb82ab69f064ff2848d3e5d85ec168cee Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Wed, 18 Dec 2024 19:15:57 +0200 Subject: [PATCH 03/16] feat(floor): spawn next floor --- src/floor/events.rs | 5 +++++ src/floor/mod.rs | 4 +++- src/floor/systems/despawn.rs | 3 +++ src/floor/systems/mod.rs | 15 +++++++++++++-- src/floor/systems/spawn.rs | 11 +++++++++++ src/maze/events.rs | 2 +- src/maze/triggers/spawn.rs | 6 ++++-- src/player/events.rs | 10 ---------- src/player/mod.rs | 4 +--- src/player/systems/ascend.rs | 15 +++++++-------- src/player/systems/descend.rs | 17 ++++++++--------- 11 files changed, 56 insertions(+), 36 deletions(-) create mode 100644 src/floor/systems/despawn.rs create mode 100644 src/floor/systems/spawn.rs diff --git a/src/floor/events.rs b/src/floor/events.rs index d9bd31c..8eb3b64 100644 --- a/src/floor/events.rs +++ b/src/floor/events.rs @@ -18,3 +18,8 @@ pub struct RespawnFloor { pub struct DespawnFloor { pub floor: u8, } + +#[derive(Debug, Reflect, Event)] +pub struct TransitionFloor { + pub floor: u8, +} diff --git a/src/floor/mod.rs b/src/floor/mod.rs index b0e8bc0..23e4944 100644 --- a/src/floor/mod.rs +++ b/src/floor/mod.rs @@ -3,7 +3,9 @@ pub mod events; mod systems; use bevy::prelude::*; +use events::TransitionFloor; pub(super) fn plugin(app: &mut App) { - app.add_plugins(systems::plugin); + app.add_event::() + .add_plugins(systems::plugin); } diff --git a/src/floor/systems/despawn.rs b/src/floor/systems/despawn.rs new file mode 100644 index 0000000..b66f570 --- /dev/null +++ b/src/floor/systems/despawn.rs @@ -0,0 +1,3 @@ +use bevy::prelude::*; + +pub(super) fn despawn_level(mut commands: Commands) {} diff --git a/src/floor/systems/mod.rs b/src/floor/systems/mod.rs index 5b1303d..cfbd806 100644 --- a/src/floor/systems/mod.rs +++ b/src/floor/systems/mod.rs @@ -1,3 +1,14 @@ -use bevy::prelude::*; +mod despawn; +mod spawn; -pub(super) fn plugin(_app: &mut App) {} +use crate::maze::MazePluginLoaded; +use bevy::prelude::*; +use despawn::despawn_level; +use spawn::spawn_floor; + +pub(super) fn plugin(app: &mut App) { + app.add_systems( + Update, + (spawn_floor, despawn_level).run_if(resource_exists::), + ); +} diff --git a/src/floor/systems/spawn.rs b/src/floor/systems/spawn.rs new file mode 100644 index 0000000..fa16052 --- /dev/null +++ b/src/floor/systems/spawn.rs @@ -0,0 +1,11 @@ +use bevy::prelude::*; + +use crate::{floor::events::TransitionFloor, maze::events::SpawnMaze}; + +pub(super) fn spawn_floor(mut commands: Commands, mut event_reader: EventReader) { + for event in event_reader.read() { + let floor = event.floor; + info!("Creating level for floor {}", floor); + commands.trigger(SpawnMaze { floor, ..default() }); + } +} diff --git a/src/maze/events.rs b/src/maze/events.rs index 24278ae..5686470 100644 --- a/src/maze/events.rs +++ b/src/maze/events.rs @@ -2,7 +2,7 @@ use bevy::prelude::*; use super::components::MazeConfig; -#[derive(Debug, Reflect, Event)] +#[derive(Debug, Reflect, Event, Default)] pub struct SpawnMaze { pub floor: u8, pub config: MazeConfig, diff --git a/src/maze/triggers/spawn.rs b/src/maze/triggers/spawn.rs index e7ed398..32e84e7 100644 --- a/src/maze/triggers/spawn.rs +++ b/src/maze/triggers/spawn.rs @@ -14,6 +14,8 @@ use std::f32::consts::{FRAC_PI_2, FRAC_PI_3, FRAC_PI_6}; use super::common::generate_maze; +const FLOOR_Y_OFFSET: u8 = 100; + pub(super) fn spawn_maze( trigger: Trigger, mut commands: Commands, @@ -24,11 +26,11 @@ pub(super) fn spawn_maze( ) { 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 y_offset = (floor - 1) * FLOOR_Y_OFFSET; let entity = commands .spawn(( @@ -37,7 +39,7 @@ pub(super) fn spawn_maze( Floor(*floor), CurrentFloor, // TODO: remove config.clone(), - Transform::from_translation(Vec3::ZERO), + Transform::from_translation(Vec3::ZERO.with_y(y_offset as f32)), Visibility::Visible, )) .id(); diff --git a/src/player/events.rs b/src/player/events.rs index 04ed340..953c8c9 100644 --- a/src/player/events.rs +++ b/src/player/events.rs @@ -8,13 +8,3 @@ pub struct RespawnPlayer; #[derive(Debug, Event)] pub struct DespawnPlayer; - -#[derive(Debug, Event)] -pub struct AscendPlayer { - pub floor: u8, -} - -#[derive(Debug, Event)] -pub struct DescendPlayer { - pub floor: u8, -} diff --git a/src/player/mod.rs b/src/player/mod.rs index 624c110..480168d 100644 --- a/src/player/mod.rs +++ b/src/player/mod.rs @@ -6,15 +6,13 @@ mod triggers; use bevy::{ecs::system::RunSystemOnce, prelude::*}; use components::Player; -use events::{AscendPlayer, DescendPlayer, DespawnPlayer, RespawnPlayer, SpawnPlayer}; +use events::{DespawnPlayer, RespawnPlayer, SpawnPlayer}; pub(super) fn plugin(app: &mut App) { app.register_type::() .add_event::() .add_event::() .add_event::() - .add_event::() - .add_event::() .add_plugins((triggers::plugin, systems::plugin)); } diff --git a/src/player/systems/ascend.rs b/src/player/systems/ascend.rs index c20f01a..8c47742 100644 --- a/src/player/systems/ascend.rs +++ b/src/player/systems/ascend.rs @@ -1,27 +1,26 @@ use bevy::prelude::*; use crate::{ - floor::components::{CurrentFloor, Floor}, - maze::components::MazeConfig, - player::{ - components::{CurrentPosition, Player}, - events::AscendPlayer, + floor::{ + components::{CurrentFloor, Floor}, + events::TransitionFloor, }, + maze::components::MazeConfig, + player::components::{CurrentPosition, Player}, }; pub(super) fn ascend_player( query: Query<&CurrentPosition, With>, maze_config_query: Query<(&MazeConfig, &Floor), With>, - mut event_writer: EventWriter, + mut event_writer: EventWriter, ) { let Ok((config, floor)) = maze_config_query.get_single() else { - warn!("No current floor configuration found"); return; }; for current_hex in query.iter() { if current_hex.0 == config.end_pos { - event_writer.send(AscendPlayer { + event_writer.send(TransitionFloor { floor: *floor.increase(), }); return; diff --git a/src/player/systems/descend.rs b/src/player/systems/descend.rs index d03b67e..852a1ab 100644 --- a/src/player/systems/descend.rs +++ b/src/player/systems/descend.rs @@ -1,27 +1,26 @@ use bevy::prelude::*; use crate::{ - floor::components::{CurrentFloor, Floor}, - maze::components::MazeConfig, - player::{ - components::{CurrentPosition, Player}, - events::DescendPlayer, + floor::{ + components::{CurrentFloor, Floor}, + events::TransitionFloor, }, + maze::components::MazeConfig, + player::components::{CurrentPosition, Player}, }; pub(super) fn descend_player( query: Query<&CurrentPosition, With>, maze_config_query: Query<(&MazeConfig, &Floor), With>, - mut event_writer: EventWriter, + mut event_writer: EventWriter, ) { let Ok((config, floor)) = maze_config_query.get_single() else { - warn!("No current floor configuration found"); return; }; for current_hex in query.iter() { - if current_hex.0 == config.start_pos { - event_writer.send(DescendPlayer { + if current_hex.0 == config.start_pos && floor.0 != 1 { + event_writer.send(TransitionFloor { floor: *floor.decrease(), }); return; From f8ea1edd87a10d8baeed9ce900de13bcbbd725e1 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Thu, 19 Dec 2024 18:38:18 +0200 Subject: [PATCH 04/16] fix(floor): spawning --- src/floor/events.rs | 8 +++++--- src/floor/systems/spawn.rs | 31 ++++++++++++++++++++++++++++--- src/maze/events.rs | 14 +++++++++++--- src/maze/systems/setup.rs | 5 ++--- src/maze/triggers/spawn.rs | 1 + src/player/systems/ascend.rs | 14 +++++--------- src/player/systems/descend.rs | 5 ++--- src/player/systems/mod.rs | 1 + 8 files changed, 55 insertions(+), 24 deletions(-) diff --git a/src/floor/events.rs b/src/floor/events.rs index 8eb3b64..1f743c8 100644 --- a/src/floor/events.rs +++ b/src/floor/events.rs @@ -19,7 +19,9 @@ pub struct DespawnFloor { pub floor: u8, } -#[derive(Debug, Reflect, Event)] -pub struct TransitionFloor { - pub floor: u8, +#[derive(Debug, Reflect, Event, Default)] +pub enum TransitionFloor { + #[default] + Ascend, + Descent, } diff --git a/src/floor/systems/spawn.rs b/src/floor/systems/spawn.rs index fa16052..91bfdc7 100644 --- a/src/floor/systems/spawn.rs +++ b/src/floor/systems/spawn.rs @@ -1,11 +1,36 @@ use bevy::prelude::*; -use crate::{floor::events::TransitionFloor, maze::events::SpawnMaze}; +use crate::{ + floor::{ + components::{CurrentFloor, Floor}, + events::TransitionFloor, + }, + maze::events::SpawnMaze, +}; + +pub(super) fn spawn_floor( + mut commands: Commands, + query: Query<(Entity, &Floor), With>, + mut event_reader: EventReader, +) { + let Ok((entity, floor)) = query.get_single() else { + return; + }; -pub(super) fn spawn_floor(mut commands: Commands, mut event_reader: EventReader) { for event in event_reader.read() { - let floor = event.floor; + dbg!(event); + let floor = match event { + TransitionFloor::Ascend => *floor.increase(), + TransitionFloor::Descent => *floor.decrease(), + }; + + if floor == 1 { + return; + } + info!("Creating level for floor {}", floor); + + commands.entity(entity).remove::(); commands.trigger(SpawnMaze { floor, ..default() }); } } diff --git a/src/maze/events.rs b/src/maze/events.rs index 5686470..ead86a9 100644 --- a/src/maze/events.rs +++ b/src/maze/events.rs @@ -1,8 +1,7 @@ +use super::components::MazeConfig; use bevy::prelude::*; -use super::components::MazeConfig; - -#[derive(Debug, Reflect, Event, Default)] +#[derive(Debug, Reflect, Event)] pub struct SpawnMaze { pub floor: u8, pub config: MazeConfig, @@ -18,3 +17,12 @@ pub struct RespawnMaze { pub struct DespawnMaze { pub floor: u8, } + +impl Default for SpawnMaze { + fn default() -> Self { + Self { + floor: 1, + config: MazeConfig::default(), + } + } +} diff --git a/src/maze/systems/setup.rs b/src/maze/systems/setup.rs index c9dd708..b26c975 100644 --- a/src/maze/systems/setup.rs +++ b/src/maze/systems/setup.rs @@ -1,7 +1,6 @@ -use crate::maze::{components::MazeConfig, events::SpawnMaze}; +use crate::maze::events::SpawnMaze; use bevy::prelude::*; pub(crate) fn setup(mut commands: Commands) { - let config = MazeConfig::default(); - commands.trigger(SpawnMaze { floor: 1, config }); + commands.trigger(SpawnMaze::default()); } diff --git a/src/maze/triggers/spawn.rs b/src/maze/triggers/spawn.rs index 32e84e7..bc03dcc 100644 --- a/src/maze/triggers/spawn.rs +++ b/src/maze/triggers/spawn.rs @@ -26,6 +26,7 @@ pub(super) fn spawn_maze( ) { let SpawnMaze { floor, config } = trigger.event(); if maze_query.iter().any(|(_, f, _)| f.0 == *floor) { + warn!("Floor {} already exists, skipping creation", floor); return; } diff --git a/src/player/systems/ascend.rs b/src/player/systems/ascend.rs index 8c47742..808120f 100644 --- a/src/player/systems/ascend.rs +++ b/src/player/systems/ascend.rs @@ -1,28 +1,24 @@ use bevy::prelude::*; use crate::{ - floor::{ - components::{CurrentFloor, Floor}, - events::TransitionFloor, - }, + floor::{components::CurrentFloor, events::TransitionFloor}, maze::components::MazeConfig, player::components::{CurrentPosition, Player}, }; pub(super) fn ascend_player( query: Query<&CurrentPosition, With>, - maze_config_query: Query<(&MazeConfig, &Floor), With>, + maze_config_query: Query<&MazeConfig, With>, mut event_writer: EventWriter, ) { - let Ok((config, floor)) = maze_config_query.get_single() else { + let Ok(config) = maze_config_query.get_single() else { + warn!("Failed to get maze configuration for current floor - cannot ascend player"); return; }; for current_hex in query.iter() { if current_hex.0 == config.end_pos { - event_writer.send(TransitionFloor { - floor: *floor.increase(), - }); + event_writer.send(TransitionFloor::Ascend); return; } } diff --git a/src/player/systems/descend.rs b/src/player/systems/descend.rs index 852a1ab..3e72798 100644 --- a/src/player/systems/descend.rs +++ b/src/player/systems/descend.rs @@ -15,14 +15,13 @@ pub(super) fn descend_player( mut event_writer: EventWriter, ) { let Ok((config, floor)) = maze_config_query.get_single() else { + warn!("Failed to get maze configuration for current floor - cannot descend player"); return; }; for current_hex in query.iter() { if current_hex.0 == config.start_pos && floor.0 != 1 { - event_writer.send(TransitionFloor { - floor: *floor.decrease(), - }); + event_writer.send(TransitionFloor::Descent); return; } } diff --git a/src/player/systems/mod.rs b/src/player/systems/mod.rs index df081cd..647cfb8 100644 --- a/src/player/systems/mod.rs +++ b/src/player/systems/mod.rs @@ -3,6 +3,7 @@ mod descend; mod input; mod movement; pub mod setup; +mod transition_floor; use crate::maze::MazePluginLoaded; use ascend::ascend_player; From 6c07bc0670343cb613d6c6d94649ab507c699a36 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 22 Dec 2024 18:25:40 +0200 Subject: [PATCH 05/16] feat(floor): add NextFloor component --- src/floor/components.rs | 12 ++++--- src/floor/systems/despawn.rs | 2 +- src/floor/systems/mod.rs | 8 +++-- src/floor/systems/movement.rs | 59 +++++++++++++++++++++++++++++++++++ src/floor/systems/spawn.rs | 14 ++++----- src/maze/systems/setup.rs | 53 +++++++++++++++++++++++++++++-- src/maze/triggers/mod.rs | 2 +- src/maze/triggers/spawn.rs | 8 ++--- src/player/systems/ascend.rs | 3 +- src/player/systems/mod.rs | 1 - 10 files changed, 136 insertions(+), 26 deletions(-) create mode 100644 src/floor/systems/movement.rs diff --git a/src/floor/components.rs b/src/floor/components.rs index a44f17b..b3e8adf 100644 --- a/src/floor/components.rs +++ b/src/floor/components.rs @@ -8,6 +8,10 @@ pub struct Floor(pub u8); #[reflect(Component)] pub struct CurrentFloor; +#[derive(Debug, Reflect, Component)] +#[reflect(Component)] +pub struct NextFloor; + impl Default for Floor { fn default() -> Self { Self(1) @@ -15,11 +19,11 @@ impl Default for Floor { } impl Floor { - pub fn increase(&self) -> Self { + pub fn increased(&self) -> Self { Self(self.0.saturating_add(1)) } - pub fn decrease(&self) -> Self { + pub fn decreased(&self) -> Self { Self(self.0.saturating_sub(1).max(1)) } } @@ -36,7 +40,7 @@ mod tests { #[case(255, 255)] fn increase(#[case] input: u8, #[case] expected: u8) { let floor = Floor(input); - assert_eq!(*floor.increase(), expected); + assert_eq!(*floor.increased(), expected); } #[rstest] @@ -46,6 +50,6 @@ mod tests { #[case(255, 254)] fn decrease(#[case] input: u8, #[case] expected: u8) { let floor = Floor(input); - assert_eq!(*floor.decrease(), expected); + assert_eq!(*floor.decreased(), expected); } } diff --git a/src/floor/systems/despawn.rs b/src/floor/systems/despawn.rs index b66f570..2c77d52 100644 --- a/src/floor/systems/despawn.rs +++ b/src/floor/systems/despawn.rs @@ -1,3 +1,3 @@ use bevy::prelude::*; -pub(super) fn despawn_level(mut commands: Commands) {} +pub(super) fn despawn_floor(mut commands: Commands) {} diff --git a/src/floor/systems/mod.rs b/src/floor/systems/mod.rs index cfbd806..2c82479 100644 --- a/src/floor/systems/mod.rs +++ b/src/floor/systems/mod.rs @@ -1,14 +1,18 @@ mod despawn; +mod movement; mod spawn; use crate::maze::MazePluginLoaded; use bevy::prelude::*; -use despawn::despawn_level; +use despawn::despawn_floor; +use movement::floor_movement; use spawn::spawn_floor; pub(super) fn plugin(app: &mut App) { app.add_systems( Update, - (spawn_floor, despawn_level).run_if(resource_exists::), + (spawn_floor, despawn_floor, floor_movement) + .chain() + .run_if(resource_exists::), ); } diff --git a/src/floor/systems/movement.rs b/src/floor/systems/movement.rs new file mode 100644 index 0000000..be94014 --- /dev/null +++ b/src/floor/systems/movement.rs @@ -0,0 +1,59 @@ +use bevy::prelude::*; + +use crate::{ + floor::{ + components::{CurrentFloor, NextFloor}, + events::TransitionFloor, + }, + maze::{components::Maze, GlobalMazeConfig}, + player::components::{MovementSpeed, Player}, +}; + +pub(super) fn floor_movement( + mut commands: Commands, + mut maze_transforms: Query<(Entity, &mut Transform), With>, + current_floor: Query>, + next_floor: Query>, + player_query: Query<&MovementSpeed, With>, + time: Res