mirror of
https://github.com/kristoferssolo/maze-ascension.git
synced 2025-10-21 19:20:34 +00:00
feat(maze): use seed
This commit is contained in:
parent
24b92a24cc
commit
dca6747f83
13
Cargo.lock
generated
13
Cargo.lock
generated
@ -2327,7 +2327,7 @@ dependencies = [
|
|||||||
"hexx",
|
"hexx",
|
||||||
"rand",
|
"rand",
|
||||||
"rand_chacha",
|
"rand_chacha",
|
||||||
"thiserror 2.0.3",
|
"thiserror 2.0.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2682,6 +2682,7 @@ dependencies = [
|
|||||||
"hexx",
|
"hexx",
|
||||||
"log",
|
"log",
|
||||||
"rand",
|
"rand",
|
||||||
|
"thiserror 2.0.5",
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -3862,11 +3863,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "2.0.3"
|
version = "2.0.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa"
|
checksum = "643caef17e3128658ff44d85923ef2d28af81bb71e0d67bbfe1d76f19a73e053"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl 2.0.3",
|
"thiserror-impl 2.0.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3882,9 +3883,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "2.0.3"
|
version = "2.0.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568"
|
checksum = "995d0bbc9995d1f19d28b7215a9352b0fc3cd3a2d2ec95c2cadc485cdedbcdde"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|||||||
@ -21,6 +21,7 @@ hexx = { version = "0.18", features = ["bevy_reflect", "grid"] }
|
|||||||
hexlab = { version = "0.1", features = ["bevy"] }
|
hexlab = { version = "0.1", features = ["bevy"] }
|
||||||
bevy-inspector-egui = { version = "0.27", optional = true }
|
bevy-inspector-egui = { version = "0.27", optional = true }
|
||||||
bevy_egui = { version = "0.30", optional = true }
|
bevy_egui = { version = "0.30", optional = true }
|
||||||
|
thiserror = "2.0"
|
||||||
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
|||||||
@ -12,9 +12,12 @@ use bevy::{
|
|||||||
|
|
||||||
use bevy_inspector_egui::{bevy_egui::EguiContext, DefaultInspectorConfigPlugin};
|
use bevy_inspector_egui::{bevy_egui::EguiContext, DefaultInspectorConfigPlugin};
|
||||||
|
|
||||||
use crate::{maze::events::RecreateMazeEvent, screens::Screen};
|
use crate::{
|
||||||
|
maze::{events::RecreateMazeEvent, MazeConfig},
|
||||||
|
screens::Screen,
|
||||||
|
};
|
||||||
use bevy_egui::{
|
use bevy_egui::{
|
||||||
egui::{self, Button, Color32, ScrollArea},
|
egui::{self, Button, Color32, DragValue, ScrollArea},
|
||||||
EguiPlugin,
|
EguiPlugin,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -52,15 +55,72 @@ fn inspector_ui(world: &mut World) {
|
|||||||
ScrollArea::vertical().show(ui, |ui| {
|
ScrollArea::vertical().show(ui, |ui| {
|
||||||
bevy_inspector_egui::bevy_inspector::ui_for_world(world, ui);
|
bevy_inspector_egui::bevy_inspector::ui_for_world(world, ui);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
egui::Window::new("Maze Controls").show(egui_context.get_mut(), |ui| {
|
||||||
|
if let Some(mut maze_config) = world.get_resource_mut::<MazeConfig>() {
|
||||||
|
ui.heading("Maze Configuration");
|
||||||
|
|
||||||
|
// radius controls
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.label("Radius:");
|
||||||
|
ui.add(
|
||||||
|
DragValue::new(&mut maze_config.radius)
|
||||||
|
.speed(1)
|
||||||
|
.range(1..=100),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// height controls
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.label("Height:");
|
||||||
|
ui.add(
|
||||||
|
DragValue::new(&mut maze_config.height)
|
||||||
|
.speed(0.5)
|
||||||
|
.range(1.0..=50.),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// start position
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.label("Start Position:");
|
||||||
|
ui.add(
|
||||||
|
DragValue::new(&mut maze_config.start_pos.x)
|
||||||
|
.speed(1)
|
||||||
|
.prefix("x: "),
|
||||||
|
);
|
||||||
|
ui.add(
|
||||||
|
DragValue::new(&mut maze_config.start_pos.y)
|
||||||
|
.speed(1)
|
||||||
|
.prefix("y: "),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// end position
|
||||||
|
ui.horizontal(|ui| {
|
||||||
|
ui.label("End Position:");
|
||||||
|
ui.add(
|
||||||
|
DragValue::new(&mut maze_config.end_pos.x)
|
||||||
|
.speed(1)
|
||||||
|
.prefix("x: "),
|
||||||
|
);
|
||||||
|
ui.add(
|
||||||
|
DragValue::new(&mut maze_config.end_pos.y)
|
||||||
|
.speed(1)
|
||||||
|
.prefix("y: "),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
ui.add_space(8.);
|
ui.add_space(8.);
|
||||||
|
|
||||||
let button = Button::new("Recreate maze").fill(Color32::from_rgb(108, 108, 108));
|
let button = Button::new("Recreate maze").fill(Color32::from_rgb(108, 108, 108));
|
||||||
|
|
||||||
if ui.add(button).clicked() {
|
if ui.add(button).clicked() {
|
||||||
if let Some(mut event_writer) = world.get_resource_mut::<Events<RecreateMazeEvent>>() {
|
if let Some(mut event_writer) =
|
||||||
|
world.get_resource_mut::<Events<RecreateMazeEvent>>()
|
||||||
|
{
|
||||||
event_writer.send(RecreateMazeEvent { floor: 1 });
|
event_writer.send(RecreateMazeEvent { floor: 1 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,10 +2,7 @@ use std::f32::consts::FRAC_PI_2;
|
|||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
|
|
||||||
use super::{
|
use super::{resources::WALL_SIZE, MazeConfig};
|
||||||
resources::{HEX_SIZE, WALL_SIZE},
|
|
||||||
MazeConfig,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub(crate) struct MazeAssets {
|
pub(crate) struct MazeAssets {
|
||||||
pub(crate) hex_mesh: Handle<Mesh>,
|
pub(crate) hex_mesh: Handle<Mesh>,
|
||||||
@ -20,8 +17,8 @@ pub(crate) fn create_base_assets(
|
|||||||
config: &MazeConfig,
|
config: &MazeConfig,
|
||||||
) -> MazeAssets {
|
) -> MazeAssets {
|
||||||
MazeAssets {
|
MazeAssets {
|
||||||
hex_mesh: meshes.add(generate_hex_mesh(HEX_SIZE, config.height)),
|
hex_mesh: meshes.add(generate_hex_mesh(config.size, config.height)),
|
||||||
wall_mesh: meshes.add(generate_square_mesh(HEX_SIZE)),
|
wall_mesh: meshes.add(generate_square_mesh(config.size)),
|
||||||
hex_material: materials.add(white_material()),
|
hex_material: materials.add(white_material()),
|
||||||
wall_material: materials.add(Color::BLACK),
|
wall_material: materials.add(Color::BLACK),
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,39 +1,63 @@
|
|||||||
|
use std::num::TryFromIntError;
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use hexx::{Hex, HexLayout, HexOrientation};
|
use hexx::{Hex, HexLayout, HexOrientation};
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{rngs::StdRng, thread_rng, Rng, SeedableRng};
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
pub(crate) const HEX_SIZE: f32 = 6.;
|
|
||||||
pub(crate) const WALL_SIZE: f32 = 1.0;
|
pub(crate) const WALL_SIZE: f32 = 1.0;
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum MazeConfigError {
|
||||||
|
#[error("Failed to convert radius from u32 to i32: {0}")]
|
||||||
|
RadiusConverions(#[from] TryFromIntError),
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Reflect, Resource)]
|
#[derive(Debug, Reflect, Resource)]
|
||||||
#[reflect(Resource)]
|
#[reflect(Resource)]
|
||||||
pub struct MazeConfig {
|
pub struct MazeConfig {
|
||||||
pub radius: u32,
|
pub radius: u32,
|
||||||
pub height: f32,
|
pub height: f32,
|
||||||
|
pub size: f32,
|
||||||
pub start_pos: Hex,
|
pub start_pos: Hex,
|
||||||
pub end_pos: Hex,
|
pub end_pos: Hex,
|
||||||
|
pub seed: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MazeConfig {
|
||||||
|
fn new(
|
||||||
|
radius: u32,
|
||||||
|
height: f32,
|
||||||
|
size: f32,
|
||||||
|
seed: Option<u64>,
|
||||||
|
) -> Result<Self, MazeConfigError> {
|
||||||
|
let seed = seed.unwrap_or_else(|| thread_rng().gen());
|
||||||
|
let mut rng = StdRng::seed_from_u64(seed);
|
||||||
|
|
||||||
|
let start_pos = generate_pos(radius, &mut rng)?;
|
||||||
|
let end_pos = generate_pos(radius, &mut rng)?;
|
||||||
|
|
||||||
|
debug!("Start pos: ({},{})", start_pos.x, start_pos.y);
|
||||||
|
debug!("End pos: ({},{})", end_pos.x, end_pos.y);
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
radius: radius as u32,
|
||||||
|
height,
|
||||||
|
size,
|
||||||
|
start_pos,
|
||||||
|
end_pos,
|
||||||
|
seed,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_unchecked(radius: u32, height: f32, hex_size: f32, seed: Option<u64>) -> Self {
|
||||||
|
Self::new(radius, height, hex_size, seed)
|
||||||
|
.expect("Failed to create MazeConfig with supposedly safe values")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for MazeConfig {
|
impl Default for MazeConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let mut rng = thread_rng();
|
Self::new_unchecked(7, 20., 6., None)
|
||||||
let radius = 7;
|
|
||||||
let start_pos = Hex::new(
|
|
||||||
rng.gen_range(-radius..radius),
|
|
||||||
rng.gen_range(-radius..radius),
|
|
||||||
);
|
|
||||||
let end_pos = Hex::new(
|
|
||||||
rng.gen_range(-radius..radius),
|
|
||||||
rng.gen_range(-radius..radius),
|
|
||||||
);
|
|
||||||
debug!("Start pos: ({},{})", start_pos.x, start_pos.y);
|
|
||||||
debug!("End pos: ({},{})", end_pos.x, end_pos.y);
|
|
||||||
Self {
|
|
||||||
radius: radius as u32,
|
|
||||||
height: 20.,
|
|
||||||
start_pos,
|
|
||||||
end_pos,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,11 +66,20 @@ impl Default for MazeConfig {
|
|||||||
pub struct Layout(pub HexLayout);
|
pub struct Layout(pub HexLayout);
|
||||||
|
|
||||||
impl FromWorld for Layout {
|
impl FromWorld for Layout {
|
||||||
fn from_world(_world: &mut World) -> Self {
|
fn from_world(world: &mut World) -> Self {
|
||||||
|
let config = world.resource::<MazeConfig>();
|
||||||
Self(HexLayout {
|
Self(HexLayout {
|
||||||
orientation: HexOrientation::Flat,
|
orientation: HexOrientation::Flat,
|
||||||
hex_size: Vec2::splat(HEX_SIZE),
|
hex_size: Vec2::splat(config.size),
|
||||||
..default()
|
..default()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn generate_pos<R: Rng>(radius: u32, rng: &mut R) -> Result<Hex, MazeConfigError> {
|
||||||
|
let radius = i32::try_from(radius)?;
|
||||||
|
Ok(Hex::new(
|
||||||
|
rng.gen_range(-radius..radius),
|
||||||
|
rng.gen_range(-radius..radius),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|||||||
3
src/maze/systems/despawn.rs
Normal file
3
src/maze/systems/despawn.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
use bevy::prelude::*;
|
||||||
|
|
||||||
|
use crate::maze::components::MazeFloor;
|
||||||
@ -26,7 +26,7 @@ pub(super) fn setup_maze(
|
|||||||
) {
|
) {
|
||||||
let maze = MazeBuilder::new()
|
let maze = MazeBuilder::new()
|
||||||
.with_radius(config.radius)
|
.with_radius(config.radius)
|
||||||
// .with_seed(0)
|
.with_seed(config.seed)
|
||||||
.with_generator(GeneratorType::RecursiveBacktracking)
|
.with_generator(GeneratorType::RecursiveBacktracking)
|
||||||
.build()
|
.build()
|
||||||
.expect("Something went wrong while creating maze");
|
.expect("Something went wrong while creating maze");
|
||||||
@ -43,7 +43,7 @@ pub(super) fn setup_maze(
|
|||||||
))
|
))
|
||||||
.with_children(|parent| {
|
.with_children(|parent| {
|
||||||
for tile in maze.values() {
|
for tile in maze.values() {
|
||||||
spawn_single_hex_tile(parent, &assets, tile, &layout.0, config.height)
|
spawn_single_hex_tile(parent, &assets, tile, &layout.0, &config)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,8 @@ use hexx::HexOrientation;
|
|||||||
use crate::maze::{
|
use crate::maze::{
|
||||||
assets::MazeAssets,
|
assets::MazeAssets,
|
||||||
components::{MazeTile, MazeWall},
|
components::{MazeTile, MazeWall},
|
||||||
resources::{HEX_SIZE, WALL_SIZE},
|
resources::WALL_SIZE,
|
||||||
|
MazeConfig,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(super) fn spawn_single_hex_tile(
|
pub(super) fn spawn_single_hex_tile(
|
||||||
@ -15,7 +16,7 @@ pub(super) fn spawn_single_hex_tile(
|
|||||||
assets: &MazeAssets,
|
assets: &MazeAssets,
|
||||||
tile: &HexTile,
|
tile: &HexTile,
|
||||||
layout: &HexLayout,
|
layout: &HexLayout,
|
||||||
hex_height: f32,
|
config: &MazeConfig,
|
||||||
) {
|
) {
|
||||||
let world_pos = tile.to_vec3(layout);
|
let world_pos = tile.to_vec3(layout);
|
||||||
let rotation = match layout.orientation {
|
let rotation = match layout.orientation {
|
||||||
@ -34,11 +35,12 @@ pub(super) fn spawn_single_hex_tile(
|
|||||||
..default()
|
..default()
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
.with_children(|parent| spawn_walls(parent, assets, hex_height / 2., &tile.walls()));
|
.with_children(|parent| spawn_walls(parent, assets, config, &tile.walls()));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawn_walls(parent: &mut ChildBuilder, assets: &MazeAssets, y_offset: f32, walls: &Walls) {
|
fn spawn_walls(parent: &mut ChildBuilder, assets: &MazeAssets, config: &MazeConfig, walls: &Walls) {
|
||||||
let z_rotation = Quat::from_rotation_z(-FRAC_PI_2);
|
let z_rotation = Quat::from_rotation_z(-FRAC_PI_2);
|
||||||
|
let y_offset = config.height / 2.;
|
||||||
|
|
||||||
for i in 0..6 {
|
for i in 0..6 {
|
||||||
if !walls.contains(i) {
|
if !walls.contains(i) {
|
||||||
@ -47,8 +49,8 @@ fn spawn_walls(parent: &mut ChildBuilder, assets: &MazeAssets, y_offset: f32, wa
|
|||||||
|
|
||||||
let wall_angle = -FRAC_PI_3 * i as f32;
|
let wall_angle = -FRAC_PI_3 * i as f32;
|
||||||
|
|
||||||
let x_offset = (HEX_SIZE - WALL_SIZE) * f32::cos(wall_angle);
|
let x_offset = (config.size - WALL_SIZE) * f32::cos(wall_angle);
|
||||||
let z_offset = (HEX_SIZE - WALL_SIZE) * f32::sin(wall_angle);
|
let z_offset = (config.size - WALL_SIZE) * f32::sin(wall_angle);
|
||||||
let pos = Vec3::new(x_offset, y_offset, z_offset);
|
let pos = Vec3::new(x_offset, y_offset, z_offset);
|
||||||
|
|
||||||
let x_rotation = Quat::from_rotation_x(wall_angle + FRAC_PI_2);
|
let x_rotation = Quat::from_rotation_x(wall_angle + FRAC_PI_2);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user