feat(maze): add maze recreation ability

This commit is contained in:
Kristofers Solo 2024-12-08 17:09:21 +02:00
parent 0ca94082a9
commit 24b92a24cc
10 changed files with 116 additions and 17 deletions

View File

@ -7,23 +7,29 @@ use bevy::{
},
input::common_conditions::input_just_pressed,
prelude::*,
window::PrimaryWindow,
};
use bevy_inspector_egui::quick::WorldInspectorPlugin;
use bevy_inspector_egui::{bevy_egui::EguiContext, DefaultInspectorConfigPlugin};
use crate::screens::Screen;
use crate::{maze::events::RecreateMazeEvent, screens::Screen};
use bevy_egui::{
egui::{self, Button, Color32, ScrollArea},
EguiPlugin,
};
pub(super) fn plugin(app: &mut App) {
// Log `Screen` state transitions.
app.add_systems(Update, log_transitions::<Screen>);
// Toggle the debug overlay for UI.
app.add_plugins(DebugUiPlugin);
app.add_plugins(WorldInspectorPlugin::default());
app.add_systems(
Update,
toggle_debug_ui.run_if(input_just_pressed(TOGGLE_KEY)),
);
app.add_systems(Update, log_transitions::<Screen>)
.add_plugins(EguiPlugin)
.add_plugins(DebugUiPlugin)
.add_plugins(DefaultInspectorConfigPlugin)
.add_systems(Update, inspector_ui)
// Toggle the debug overlay for UI.
.add_systems(
Update,
toggle_debug_ui.run_if(input_just_pressed(TOGGLE_KEY)),
);
}
const TOGGLE_KEY: KeyCode = KeyCode::Backquote;
@ -31,3 +37,30 @@ const TOGGLE_KEY: KeyCode = KeyCode::Backquote;
fn toggle_debug_ui(mut options: ResMut<UiDebugOptions>) {
options.toggle();
}
fn inspector_ui(world: &mut World) {
let Ok(egui_context) = world
.query_filtered::<&mut EguiContext, With<PrimaryWindow>>()
.get_single(world)
else {
return;
};
let mut egui_context = egui_context.clone();
egui::Window::new("UI").show(egui_context.get_mut(), |ui| {
ScrollArea::vertical().show(ui, |ui| {
bevy_inspector_egui::bevy_inspector::ui_for_world(world, ui);
});
ui.add_space(8.);
let button = Button::new("Recreate maze").fill(Color32::from_rgb(108, 108, 108));
if ui.add(button).clicked() {
if let Some(mut event_writer) = world.get_resource_mut::<Events<RecreateMazeEvent>>() {
event_writer.send(RecreateMazeEvent { floor: 1 });
}
}
});
}

View File

@ -17,7 +17,7 @@ pub(crate) struct MazeAssets {
pub(crate) fn create_base_assets(
meshes: &mut ResMut<Assets<Mesh>>,
materials: &mut ResMut<Assets<StandardMaterial>>,
config: &Res<MazeConfig>,
config: &MazeConfig,
) -> MazeAssets {
MazeAssets {
hex_mesh: meshes.add(generate_hex_mesh(HEX_SIZE, config.height)),

View File

@ -2,8 +2,12 @@ use bevy::prelude::*;
#[derive(Debug, Reflect, Component)]
#[reflect(Component)]
pub(crate) struct MazeWall;
pub(crate) struct MazeFloor(pub(crate) u8);
#[derive(Debug, Reflect, Component)]
#[reflect(Component)]
pub(crate) struct MazeTile;
#[derive(Debug, Reflect, Component)]
#[reflect(Component)]
pub(crate) struct MazeWall;

6
src/maze/events.rs Normal file
View File

@ -0,0 +1,6 @@
use bevy::prelude::*;
#[derive(Debug, Event)]
pub(crate) struct RecreateMazeEvent {
pub(crate) floor: u8,
}

View File

@ -2,6 +2,7 @@ use bevy::{ecs::world::Command, prelude::*};
use plugin::MazePlugin;
mod assets;
mod components;
pub mod events;
pub mod plugin;
mod resources;
mod systems;

View File

@ -3,14 +3,22 @@ use bevy::{
prelude::*,
};
use super::{resources::Layout, systems, MazeConfig};
use super::{
events::RecreateMazeEvent,
resources::Layout,
systems::{self, recreation::handle_maze_recreation_event},
MazeConfig,
};
#[derive(Default)]
pub(crate) struct MazePlugin;
impl Plugin for MazePlugin {
fn build(&self, app: &mut App) {
app.init_resource::<MazeConfig>().init_resource::<Layout>();
app.init_resource::<MazeConfig>()
.init_resource::<Layout>()
.add_event::<RecreateMazeEvent>()
.add_systems(Update, handle_maze_recreation_event);
}
}

View File

@ -1,2 +1,3 @@
pub mod recreation;
pub mod setup;
mod spawn;

View File

@ -0,0 +1,30 @@
use bevy::prelude::*;
use crate::maze::{
components::MazeFloor, events::RecreateMazeEvent, resources::Layout, MazeConfig,
};
use super::setup::setup_maze;
pub(crate) fn handle_maze_recreation_event(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
config: Res<MazeConfig>,
layout: Res<Layout>,
query: Query<(Entity, &MazeFloor)>,
mut event_reader: EventReader<RecreateMazeEvent>,
) {
for event in event_reader.read() {
despawn_floor(&mut commands, &query, event.floor);
setup_maze(&mut commands, &mut meshes, &mut materials, &config, &layout);
}
}
fn despawn_floor(commands: &mut Commands, query: &Query<(Entity, &MazeFloor)>, floor_num: u8) {
for (entity, maze_floor) in query.iter() {
if maze_floor.0 == floor_num {
commands.entity(entity).despawn_recursive();
}
}
}

View File

@ -1,7 +1,9 @@
use bevy::prelude::*;
use hexlab::{GeneratorType, MazeBuilder};
use crate::maze::{assets::create_base_assets, resources::Layout, MazeConfig};
use crate::maze::{
assets::create_base_assets, components::MazeFloor, resources::Layout, MazeConfig,
};
use super::spawn::spawn_single_hex_tile;
@ -11,6 +13,16 @@ pub(crate) fn setup(
mut materials: ResMut<Assets<StandardMaterial>>,
config: Res<MazeConfig>,
layout: Res<Layout>,
) {
setup_maze(&mut commands, &mut meshes, &mut materials, &config, &layout);
}
pub(super) fn setup_maze(
commands: &mut Commands,
meshes: &mut ResMut<Assets<Mesh>>,
materials: &mut ResMut<Assets<StandardMaterial>>,
config: &MazeConfig,
layout: &Layout,
) {
let maze = MazeBuilder::new()
.with_radius(config.radius)
@ -19,10 +31,11 @@ pub(crate) fn setup(
.build()
.expect("Something went wrong while creating maze");
let assets = create_base_assets(&mut meshes, &mut materials, &config);
let assets = create_base_assets(meshes, materials, config);
commands
.spawn((
Name::new("Floor"),
MazeFloor(1),
SpatialBundle {
transform: Transform::from_translation(Vec3::ZERO),
..default()

View File

@ -6,6 +6,7 @@ use hexx::HexOrientation;
use crate::maze::{
assets::MazeAssets,
components::{MazeTile, MazeWall},
resources::{HEX_SIZE, WALL_SIZE},
};
@ -25,6 +26,7 @@ pub(super) fn spawn_single_hex_tile(
parent
.spawn((
Name::new(format!("Hex {}", tile.to_string())),
MazeTile,
PbrBundle {
mesh: assets.hex_mesh.clone(),
material: assets.hex_material.clone(),
@ -64,6 +66,7 @@ fn spawn_single_wall(
) {
parent.spawn((
Name::new("Wall"),
MazeWall,
PbrBundle {
mesh: asstets.wall_mesh.clone(),
material: asstets.wall_material.clone(),