From 0f4899319dd53e8646e507a4969c53aa692528ea Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Tue, 7 Jan 2025 10:25:42 +0200 Subject: [PATCH 1/4] refactor(themes): separate into files --- Cargo.lock | 2 +- Cargo.toml | 2 +- justfile | 2 +- src/screens/loading.rs | 2 +- src/theme/assets.rs | 24 +++++++++ src/theme/components.rs | 16 ++++++ src/theme/events.rs | 6 +++ src/theme/interaction.rs | 102 ------------------------------------ src/theme/mod.rs | 16 ++++-- src/theme/systems/button.rs | 52 ++++++++++++++++++ src/theme/systems/mod.rs | 18 +++++++ src/theme/widgets.rs | 10 ++-- 12 files changed, 140 insertions(+), 112 deletions(-) create mode 100644 src/theme/assets.rs create mode 100644 src/theme/components.rs create mode 100644 src/theme/events.rs delete mode 100644 src/theme/interaction.rs create mode 100644 src/theme/systems/button.rs create mode 100644 src/theme/systems/mod.rs diff --git a/Cargo.lock b/Cargo.lock index a3d251d..9644b97 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3129,7 +3129,7 @@ dependencies = [ [[package]] name = "maze-ascension" -version = "1.0.2" +version = "1.0.3" dependencies = [ "anyhow", "bevy", diff --git a/Cargo.toml b/Cargo.toml index 3ef7be1..9d09bdc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "maze-ascension" authors = ["Kristofers Solo "] -version = "1.0.2" +version = "1.0.3" edition = "2021" [dependencies] diff --git a/justfile b/justfile index e75c474..a5ebc42 100644 --- a/justfile +++ b/justfile @@ -12,7 +12,7 @@ native-release: # Run web dev web-dev: - RUST_BACKTRACE=full trunk serve + RUSTC_WRAPPER=sccache RUST_BACKTRACE=full trunk serve # Run web release web-release: diff --git a/src/screens/loading.rs b/src/screens/loading.rs index f96d866..9c742be 100644 --- a/src/screens/loading.rs +++ b/src/screens/loading.rs @@ -7,7 +7,7 @@ use crate::{ hint::assets::HintAssets, player::assets::PlayerAssets, screens::Screen, - theme::{interaction::InteractionAssets, prelude::*}, + theme::{assets::InteractionAssets, prelude::*}, }; pub fn plugin(app: &mut App) { diff --git a/src/theme/assets.rs b/src/theme/assets.rs new file mode 100644 index 0000000..6a0a962 --- /dev/null +++ b/src/theme/assets.rs @@ -0,0 +1,24 @@ +use bevy::prelude::*; + +#[derive(Resource, Asset, Reflect, Clone)] +pub struct InteractionAssets { + #[dependency] + pub(super) hover: Handle, + #[dependency] + pub(super) press: Handle, +} + +impl InteractionAssets { + pub const PATH_BUTTON_HOVER: &'static str = "audio/sound_effects/button_hover.ogg"; + pub const PATH_BUTTON_PRESS: &'static str = "audio/sound_effects/button_press.ogg"; +} + +impl FromWorld for InteractionAssets { + fn from_world(world: &mut World) -> Self { + let assets = world.resource::(); + Self { + hover: assets.load(Self::PATH_BUTTON_HOVER), + press: assets.load(Self::PATH_BUTTON_PRESS), + } + } +} diff --git a/src/theme/components.rs b/src/theme/components.rs new file mode 100644 index 0000000..de7d5b8 --- /dev/null +++ b/src/theme/components.rs @@ -0,0 +1,16 @@ +use bevy::prelude::*; + +/// Palette for widget interactions. Add this to an entity that supports +/// [`Interaction`]s, such as a button, to change its [`BackgroundColor`] based +/// on the current interaction state. +#[derive(Component, Debug, Reflect)] +#[reflect(Component)] +pub struct InteractionPalette { + pub none: Color, + pub hovered: Color, + pub pressed: Color, +} + +#[derive(Debug, Reflect, Component)] +#[reflect(Component)] +pub struct UrlLink(pub String); diff --git a/src/theme/events.rs b/src/theme/events.rs new file mode 100644 index 0000000..ca3a63d --- /dev/null +++ b/src/theme/events.rs @@ -0,0 +1,6 @@ +use bevy::prelude::*; + +/// Event triggered on a UI entity when the [`Interaction`] component on the same entity changes to +/// [`Interaction::Pressed`]. Observe this event to detect e.g. button presses. +#[derive(Event)] +pub struct OnPress; diff --git a/src/theme/interaction.rs b/src/theme/interaction.rs deleted file mode 100644 index c1df879..0000000 --- a/src/theme/interaction.rs +++ /dev/null @@ -1,102 +0,0 @@ -use bevy::prelude::*; - -use crate::{asset_tracking::LoadResource, audio::SoundEffect}; - -pub(super) fn plugin(app: &mut App) { - app.register_type::(); - app.load_resource::(); - app.add_systems( - Update, - ( - trigger_on_press, - apply_interaction_palette, - trigger_interaction_sound_effect, - ) - .run_if(resource_exists::), - ); -} - -/// Palette for widget interactions. Add this to an entity that supports -/// [`Interaction`]s, such as a button, to change its [`BackgroundColor`] based -/// on the current interaction state. -#[derive(Component, Debug, Reflect)] -#[reflect(Component)] -pub struct InteractionPalette { - pub none: Color, - pub hovered: Color, - pub pressed: Color, -} - -/// Event triggered on a UI entity when the [`Interaction`] component on the same entity changes to -/// [`Interaction::Pressed`]. Observe this event to detect e.g. button presses. -#[derive(Event)] -pub struct OnPress; - -fn trigger_on_press( - interaction_query: Query<(Entity, &Interaction), Changed>, - mut commands: Commands, -) { - for (entity, interaction) in &interaction_query { - if matches!(interaction, Interaction::Pressed) { - commands.trigger_targets(OnPress, entity); - } - } -} - -fn apply_interaction_palette( - mut palette_query: Query< - (&Interaction, &InteractionPalette, &mut BackgroundColor), - Changed, - >, -) { - for (interaction, palette, mut background) in &mut palette_query { - *background = match interaction { - Interaction::None => palette.none, - Interaction::Hovered => palette.hovered, - Interaction::Pressed => palette.pressed, - } - .into(); - } -} - -#[derive(Resource, Asset, Reflect, Clone)] -pub struct InteractionAssets { - #[dependency] - hover: Handle, - #[dependency] - press: Handle, -} - -impl InteractionAssets { - pub const PATH_BUTTON_HOVER: &'static str = "audio/sound_effects/button_hover.ogg"; - pub const PATH_BUTTON_PRESS: &'static str = "audio/sound_effects/button_press.ogg"; -} - -impl FromWorld for InteractionAssets { - fn from_world(world: &mut World) -> Self { - let assets = world.resource::(); - Self { - hover: assets.load(Self::PATH_BUTTON_HOVER), - press: assets.load(Self::PATH_BUTTON_PRESS), - } - } -} - -fn trigger_interaction_sound_effect( - interaction_query: Query<&Interaction, Changed>, - interaction_assets: Res, - mut commands: Commands, -) { - for interaction in &interaction_query { - let source = match interaction { - Interaction::Hovered => interaction_assets.hover.clone(), - Interaction::Pressed => interaction_assets.press.clone(), - _ => continue, - }; - commands.spawn(( - AudioPlayer::(source), - PlaybackSettings::DESPAWN, - SoundEffect, - )); - } -} diff --git a/src/theme/mod.rs b/src/theme/mod.rs index 86f1e5c..f64b348 100644 --- a/src/theme/mod.rs +++ b/src/theme/mod.rs @@ -2,23 +2,33 @@ // Unused utilities may trigger this lints undesirably. +pub mod assets; mod colorscheme; -pub mod interaction; +pub mod components; +pub mod events; pub mod palette; +mod systems; mod widgets; #[allow(unused_imports)] pub mod prelude { pub use super::{ colorscheme::{ColorScheme, ColorSchemeWrapper}, - interaction::{InteractionPalette, OnPress}, + components::{InteractionPalette, UrlLink}, + events::OnPress, palette as ui_palette, widgets::{Containers as _, Widgets as _}, }; } +use assets::InteractionAssets; use bevy::prelude::*; +use prelude::InteractionPalette; + +use crate::asset_tracking::LoadResource; pub(super) fn plugin(app: &mut App) { - app.add_plugins(interaction::plugin); + app.register_type::(); + app.load_resource::(); + app.add_plugins(systems::plugin); } diff --git a/src/theme/systems/button.rs b/src/theme/systems/button.rs new file mode 100644 index 0000000..76242e8 --- /dev/null +++ b/src/theme/systems/button.rs @@ -0,0 +1,52 @@ +use bevy::prelude::*; + +use crate::{ + audio::SoundEffect, + theme::{assets::InteractionAssets, events::OnPress, prelude::InteractionPalette}, +}; + +pub fn trigger_on_press( + interaction_query: Query<(Entity, &Interaction), Changed>, + mut commands: Commands, +) { + for (entity, interaction) in &interaction_query { + if matches!(interaction, Interaction::Pressed) { + commands.trigger_targets(OnPress, entity); + } + } +} + +pub fn apply_interaction_palette( + mut palette_query: Query< + (&Interaction, &InteractionPalette, &mut BackgroundColor), + Changed, + >, +) { + for (interaction, palette, mut background) in &mut palette_query { + *background = match interaction { + Interaction::None => palette.none, + Interaction::Hovered => palette.hovered, + Interaction::Pressed => palette.pressed, + } + .into(); + } +} + +pub fn trigger_interaction_sound_effect( + interaction_query: Query<&Interaction, Changed>, + interaction_assets: Res, + mut commands: Commands, +) { + for interaction in &interaction_query { + let source = match interaction { + Interaction::Hovered => interaction_assets.hover.clone(), + Interaction::Pressed => interaction_assets.press.clone(), + _ => continue, + }; + commands.spawn(( + AudioPlayer::(source), + PlaybackSettings::DESPAWN, + SoundEffect, + )); + } +} diff --git a/src/theme/systems/mod.rs b/src/theme/systems/mod.rs new file mode 100644 index 0000000..875a6fe --- /dev/null +++ b/src/theme/systems/mod.rs @@ -0,0 +1,18 @@ +mod button; + +use bevy::prelude::*; +use button::{apply_interaction_palette, trigger_interaction_sound_effect, trigger_on_press}; + +use super::assets::InteractionAssets; + +pub(super) fn plugin(app: &mut App) { + app.add_systems( + Update, + ( + trigger_on_press, + apply_interaction_palette, + trigger_interaction_sound_effect, + ) + .run_if(resource_exists::), + ); +} diff --git a/src/theme/widgets.rs b/src/theme/widgets.rs index 85f1962..df9107b 100644 --- a/src/theme/widgets.rs +++ b/src/theme/widgets.rs @@ -1,10 +1,13 @@ //! Helper traits for creating common widgets. -use bevy::{ecs::system::EntityCommands, prelude::*, ui::Val::*}; +use bevy::{ + ecs::system::EntityCommands, prelude::*, ui::Val::*, window::SystemCursorIcon, + winit::cursor::CursorIcon, +}; use rose_pine::RosePineDawn; -use super::prelude::ColorScheme; -use crate::theme::{interaction::InteractionPalette, palette::*}; +use super::prelude::{ColorScheme, InteractionPalette}; +use crate::theme::palette::*; /// An extension trait for spawning UI widgets. pub trait Widgets { @@ -35,6 +38,7 @@ impl Widgets for T { border: UiRect::all(Px(4.)), ..default() }, + CursorIcon::System(SystemCursorIcon::Pointer), BorderRadius::all(Px(8.)), BorderColor(RosePineDawn::Text.to_color()), InteractionPalette { From e9f02e362a9da400f3b52c7de60e59d480633c27 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Wed, 8 Jan 2025 18:27:07 +0200 Subject: [PATCH 2/4] feat(maze): add Coordinates trait --- Cargo.lock | 7 ++ Cargo.toml | 1 + src/maze/components.rs | 110 ++++++++++++++++++------------- src/maze/coordinates.rs | 139 ++++++++++++++++++++++++++++++++++++++++ src/maze/errors.rs | 6 +- src/maze/mod.rs | 1 + 6 files changed, 219 insertions(+), 45 deletions(-) create mode 100644 src/maze/coordinates.rs diff --git a/Cargo.lock b/Cargo.lock index 9644b97..8243877 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1614,6 +1614,12 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "claims" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bba18ee93d577a8428902687bcc2b6b45a56b1981a1f6d779731c86cc4c5db18" + [[package]] name = "clang-sys" version = "1.8.1" @@ -3135,6 +3141,7 @@ dependencies = [ "bevy", "bevy-inspector-egui", "bevy_egui", + "claims", "hexlab", "hexx", "log", diff --git a/Cargo.toml b/Cargo.toml index 9d09bdc..200ba1e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ anyhow = "1" strum = { version = "0.26", features = ["derive"] } [dev-dependencies] +claims = "0.8.0" rstest = "0.24" rstest_reuse = "0.7" test-log = { version = "0.2.16", default-features = false, features = [ diff --git a/src/maze/components.rs b/src/maze/components.rs index 537394e..130365e 100644 --- a/src/maze/components.rs +++ b/src/maze/components.rs @@ -3,7 +3,7 @@ //! Module defines the core components and configuration structures used //! for maze generation and rendering, including hexagonal maze layouts, //! tiles, walls, and maze configuration. -use super::GlobalMazeConfig; +use super::{coordinates::is_within_radius, GlobalMazeConfig}; use crate::floor::components::Floor; use bevy::prelude::*; @@ -110,15 +110,16 @@ impl Default for MazeConfig { /// A valid Hex coordinate within the specified radius fn generate_pos(radius: u16, rng: &mut R) -> Hex { let radius = radius as i32; - loop { - let q = rng.gen_range(-radius..=radius); - let r = rng.gen_range(-radius..=radius); - let s = -q - r; // Calculate third coordinate (axial coordinates: q + r + s = 0) - // Check if the position is within the hexagonal radius - // Using the formula: max(abs(q), abs(r), abs(s)) <= radius - if q.abs().max(r.abs()).max(s.abs()) <= radius { - return Hex::new(q, r); + loop { + // Generate coordinates using cube coordinate bounds + let q = rng.gen_range(-radius..=radius); + let r = rng.gen_range((-radius).max(-q - radius)..=radius.min(-q + radius)); + + if let Ok(is_valid) = is_within_radius(radius, &(q, r)) { + if is_valid { + return Hex::new(q, r); + } } } } @@ -126,20 +127,9 @@ fn generate_pos(radius: u16, rng: &mut R) -> Hex { #[cfg(test)] mod tests { use super::*; + use claims::*; use rstest::*; - fn is_within_radius(hex: Hex, radius: u16) -> bool { - let q = hex.x; - let r = hex.y; - let s = -q - r; - q.abs().max(r.abs()).max(s.abs()) <= radius as i32 - } - - #[fixture] - fn test_radius() -> Vec { - vec![1, 2, 5, 8] - } - #[rstest] #[case(1)] #[case(2)] @@ -156,18 +146,8 @@ mod tests { assert_eq!(config.seed, 12345); assert_eq!(config.layout.orientation, orientation); - assert!( - is_within_radius(config.start_pos, radius), - "Start pos {:?} outside radius {}", - config.start_pos, - radius - ); - assert!( - is_within_radius(config.end_pos, radius), - "End pos {:?} outside radius {}", - config.end_pos, - radius - ); + assert_ok!(is_within_radius(radius, &config.start_pos),); + assert_ok!(is_within_radius(radius, &config.end_pos)); assert_ne!(config.start_pos, config.end_pos); } @@ -178,13 +158,13 @@ mod tests { let config = MazeConfig::default(); let radius = config.radius; - assert!(is_within_radius(config.start_pos, radius)); - assert!(is_within_radius(config.end_pos, radius)); + assert_ok!(is_within_radius(radius, &config.start_pos)); + assert_ok!(is_within_radius(radius, &config.end_pos)); assert_ne!(config.start_pos, config.end_pos); } } - #[rstest] + #[test] fn maze_config_default_with_seeds() { let test_seeds = [ None, @@ -206,8 +186,8 @@ mod tests { assert_eq!(config.radius, 8); assert_eq!(config.layout.orientation, HexOrientation::Flat); - assert!(is_within_radius(config.start_pos, 8)); - assert!(is_within_radius(config.end_pos, 8)); + assert_ok!(is_within_radius(8, &config.start_pos)); + assert_ok!(is_within_radius(8, &config.end_pos)); assert_ne!(config.start_pos, config.end_pos); } } @@ -238,12 +218,7 @@ mod tests { for _ in 0..10 { let pos = generate_pos(radius, &mut rng); - assert!( - is_within_radius(pos, radius), - "Position {:?} outside radius {}", - pos, - radius - ); + assert_ok!(is_within_radius(radius, &pos),); } } @@ -317,4 +292,51 @@ mod tests { assert_eq!(config.layout.hex_size.x, 0.0); assert_eq!(config.layout.hex_size.y, 0.0); } + + #[test] + fn basic_generation() { + let mut rng = thread_rng(); + let radius = 2; + let hex = generate_pos(radius, &mut rng); + + // Test that generated position is within radius + assert_ok!(is_within_radius(radius as i32, &(hex.x, hex.y))); + } + + #[rstest] + #[case(1)] + #[case(2)] + #[case(3)] + #[case(6)] + fn multiple_radii(#[case] radius: u16) { + let mut rng = thread_rng(); + + // Generate multiple points for each radius + for _ in 0..100 { + let hex = generate_pos(radius, &mut rng); + assert_ok!(is_within_radius(radius, &hex)); + } + } + + #[test] + fn zero_radius() { + let mut rng = thread_rng(); + let hex = generate_pos(0, &mut rng); + + // With radius 0, only (0,0) should be possible + assert_eq!(hex.x, 0); + assert_eq!(hex.y, 0); + } + + #[test] + fn large_radius() { + let mut rng = thread_rng(); + let radius = 100; + let iterations = 100; + + for _ in 0..iterations { + let hex = generate_pos(radius, &mut rng); + assert_ok!(is_within_radius(radius, &hex)); + } + } } diff --git a/src/maze/coordinates.rs b/src/maze/coordinates.rs new file mode 100644 index 0000000..14447d4 --- /dev/null +++ b/src/maze/coordinates.rs @@ -0,0 +1,139 @@ +use hexx::Hex; + +use super::errors::RadiusError; + +pub trait Coordinates { + fn get_coords(&self) -> (i32, i32); +} + +impl Coordinates for (i32, i32) { + fn get_coords(&self) -> (i32, i32) { + *self + } +} + +impl Coordinates for Hex { + fn get_coords(&self) -> (i32, i32) { + (self.x, self.y) + } +} + +pub fn is_within_radius(radius: R, coords: &C) -> Result +where + R: Into, + C: Coordinates, +{ + let radius = radius.into(); + + if radius < 0 { + return Err(RadiusError::NegativeRadius(radius)); + } + + let (q, r) = coords.get_coords(); + let s = -q - r; // Calculate third axial coordinate (q + r + s = 0) + + Ok(q.abs().max(r.abs()).max(s.abs()) <= radius) +} + +#[cfg(test)] +mod tests { + use super::*; + use claims::*; + use rstest::*; + + #[rstest] + // Original test cases + #[case(0, (0, 0), true)] // Center point + #[case(1, (1, 0), true)] // Point at radius 1 + #[case(1, (2, 0), false)] // Point outside radius 1 + #[case(2, (2, 0), true)] // East + #[case(2, (0, 2), true)] // Southeast + #[case(2, (-2, 2), true)] // Southwest + #[case(2, (-2, 0), true)] // West + #[case(2, (0, -2), true)] // Northwest + #[case(2, (2, -2), true)] // Northeast + #[case(2, (3, 0), false)] // Just outside radius 2 + // Large radius test cases + #[case(6, (6, 0), true)] // East at radius 6 + #[case(6, (0, 6), true)] // Southeast at radius 6 + #[case(6, (-6, 6), true)] // Southwest at radius 6 + #[case(6, (-6, 0), true)] // West at radius 6 + #[case(6, (0, -6), true)] // Northwest at radius 6 + #[case(6, (6, -6), true)] // Northeast at radius 6 + #[case(6, (7, 0), false)] // Just outside radius 6 east + #[case(6, (4, 4), false)] // Outside radius 6 diagonal + #[case(6, (5, 5), false)] // Outside radius 6 diagonal + // Edge cases with large radius + #[case(6, (6, -3), true)] // Complex position within radius 6 + #[case(6, (-3, 6), true)] // Complex position within radius 6 + #[case(6, (3, -6), true)] // Complex position within radius 6 + #[case(6, (7, -7), false)] // Outside radius 6 corner + fn valid_radius_tuple(#[case] radius: i32, #[case] pos: (i32, i32), #[case] expected: bool) { + let result = is_within_radius(radius, &pos); + assert_ok_eq!(result, expected); + } + + #[rstest] + // Large radius test cases for Hex struct + #[case(6, (6, 0), true)] // East at radius 6 + #[case(6, (0, 6), true)] // Southeast at radius 6 + #[case(6, (-6, 6), true)] // Southwest at radius 6 + #[case(6, (-6, 0), true)] // West at radius 6 + #[case(6, (0, -6), true)] // Northwest at radius 6 + #[case(6, (6, -6), true)] // Northeast at radius 6 + #[case(6, (4, 4), false)] // Outside radius 6 diagonal + #[case(6, (5, 5), false)] // Outside radius 6 diagonal + fn valid_radius_hex(#[case] radius: i32, #[case] pos: (i32, i32), #[case] expected: bool) { + let hex = Hex::from(pos); + let result = is_within_radius(radius, &hex); + assert_ok_eq!(result, expected); + } + + #[rstest] + #[case(-1)] + #[case(-2)] + #[case(-5)] + fn negative_radius(#[case] radius: i32) { + let result = is_within_radius(radius, &(0, 0)); + assert_err!(&result); + } + + #[test] + fn boundary_points() { + let radius = 3; + // Test points exactly on the boundary of radius 3 + assert_ok_eq!(is_within_radius(radius, &(3, 0)), true); // East boundary + assert_ok_eq!(is_within_radius(radius, &(0, 3)), true); // Southeast boundary + assert_ok_eq!(is_within_radius(radius, &(-3, 3)), true); // Southwest boundary + assert_ok_eq!(is_within_radius(radius, &(-3, 0)), true); // West boundary + assert_ok_eq!(is_within_radius(radius, &(0, -3)), true); // Northwest boundary + assert_ok_eq!(is_within_radius(radius, &(3, -3)), true); // Northeast boundary + } + + #[test] + fn large_boundary_points() { + let radius = 6; + // Test points exactly on the boundary of radius 6 + assert_ok_eq!(is_within_radius(radius, &(6, 0)), true); // East boundary + assert_ok_eq!(is_within_radius(radius, &(0, 6)), true); // Southeast boundary + assert_ok_eq!(is_within_radius(radius, &(-6, 6)), true); // Southwest boundary + assert_ok_eq!(is_within_radius(radius, &(-6, 0)), true); // West boundary + assert_ok_eq!(is_within_radius(radius, &(0, -6)), true); // Northwest boundary + assert_ok_eq!(is_within_radius(radius, &(6, -6)), true); // Northeast boundary + + // Test points just outside the boundary + assert_ok_eq!(is_within_radius(radius, &(7, 0)), false); // Just outside east + assert_ok_eq!(is_within_radius(radius, &(0, 7)), false); // Just outside southeast + assert_ok_eq!(is_within_radius(radius, &(-7, 7)), false); // Just outside southwest + } + + #[test] + fn different_coordinate_types() { + // Test with tuple coordinates + assert_ok_eq!(is_within_radius(2, &(1, 1)), true); + + // Test with Hex struct + let hex = Hex { x: 1, y: 1 }; + assert_ok_eq!(is_within_radius(2, &hex), true); + } +} diff --git a/src/maze/errors.rs b/src/maze/errors.rs index f287bdc..2a186da 100644 --- a/src/maze/errors.rs +++ b/src/maze/errors.rs @@ -25,7 +25,11 @@ pub enum MazeError { Other(#[from] anyhow::Error), } -pub type MazeResult = Result; +#[derive(Debug, Error)] +pub enum RadiusError { + #[error("Radius cannot be negative: {0}")] + NegativeRadius(i32), +} impl MazeError { pub fn config_error(msg: impl Into) -> Self { diff --git a/src/maze/mod.rs b/src/maze/mod.rs index 648f171..485961e 100644 --- a/src/maze/mod.rs +++ b/src/maze/mod.rs @@ -1,6 +1,7 @@ mod assets; pub mod commands; pub mod components; +pub mod coordinates; pub mod errors; pub mod resources; mod systems; From 95b173c5042f75cc6a2df6cd15ab3c82dd400536 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Thu, 9 Jan 2025 21:13:31 +0200 Subject: [PATCH 3/4] fix: typo --- Cargo.lock | 1 + Cargo.toml | 1 + justfile | 4 ++-- src/floor/systems/movement.rs | 22 +++++++++++++++++++--- src/maze/components.rs | 10 +++------- 5 files changed, 26 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8243877..f049ca9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3146,6 +3146,7 @@ dependencies = [ "hexx", "log", "rand", + "rayon", "rstest", "rstest_reuse", "strum", diff --git a/Cargo.toml b/Cargo.toml index 200ba1e..57f938c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ strum = { version = "0.26", features = ["derive"] } [dev-dependencies] claims = "0.8.0" +rayon = "1.10.0" rstest = "0.24" rstest_reuse = "0.7" test-log = { version = "0.2.16", default-features = false, features = [ diff --git a/justfile b/justfile index a5ebc42..eea0280 100644 --- a/justfile +++ b/justfile @@ -20,8 +20,8 @@ web-release: # Run tests test: - RUSTC_WRAPPER=sccache RUST_BACKTRACE=full cargo test --doc --locked --workspace --no-default-features - RUSTC_WRAPPER=sccache RUST_BACKTRACE=full cargo nextest run --no-default-features --all-targets + RUSTC_WRAPPER=sccache cargo test --doc --locked --workspace --no-default-features + RUSTC_WRAPPER=sccache cargo nextest run --no-default-features --all-targets # Run CI localy ci: diff --git a/src/floor/systems/movement.rs b/src/floor/systems/movement.rs index 526d2f8..fccabac 100644 --- a/src/floor/systems/movement.rs +++ b/src/floor/systems/movement.rs @@ -4,7 +4,7 @@ use crate::{ components::{CurrentFloor, Floor, FloorYTarget}, events::TransitionFloor, }, - maze::components::HexMaze, + maze::components::{HexMaze, MazeConfig}, player::components::{MovementSpeed, Player}, }; @@ -18,13 +18,22 @@ use bevy::prelude::*; /// - Removes FloorYTarget component when floor reaches destination pub fn move_floors( mut commands: Commands, - mut maze_query: Query<(Entity, &mut Transform, &FloorYTarget), With>, + mut maze_query: Query< + ( + Entity, + &mut Transform, + &FloorYTarget, + &MazeConfig, + Has, + ), + With, + >, player_query: Query<&MovementSpeed, With>, time: Res