mirror of
https://github.com/kristoferssolo/maze-ascension.git
synced 2025-10-21 19:20:34 +00:00
docs: add comments
This commit is contained in:
parent
cfaf565891
commit
3d158a4e7c
@ -10,6 +10,12 @@ use crate::{
|
||||
|
||||
use bevy::prelude::*;
|
||||
|
||||
/// Move floor entities to their target Y positions based on movement speed
|
||||
///
|
||||
/// # Behavior
|
||||
/// - Calculates movement distance based on player speed and delta time
|
||||
/// - Moves floors towards their target Y position
|
||||
/// - Removes FloorYTarget component when floor reaches destination
|
||||
pub fn move_floors(
|
||||
mut commands: Commands,
|
||||
mut maze_query: Query<(Entity, &mut Transform, &FloorYTarget), With<FloorYTarget>>,
|
||||
@ -30,6 +36,13 @@ pub fn move_floors(
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle floor transition events by setting up floor movement targets
|
||||
///
|
||||
/// # Behavior
|
||||
/// - Checks if any floors are currently moving
|
||||
/// - Processes floor transition events
|
||||
/// - Sets target Y positions for all maze entities
|
||||
/// - Updates current and next floor designations
|
||||
pub fn handle_floor_transition_events(
|
||||
mut commands: Commands,
|
||||
mut maze_query: Query<(Entity, &Transform, &Floor, Option<&FloorYTarget>), With<HexMaze>>,
|
||||
|
||||
@ -1,8 +1,14 @@
|
||||
//! Maze asset management and generation.
|
||||
//!
|
||||
//! Module handles the creation and management of meshes and materials
|
||||
//! used in the maze visualization, including hexagonal tiles and walls.
|
||||
|
||||
use super::resources::GlobalMazeConfig;
|
||||
use crate::{
|
||||
constants::WALL_OVERLAP_MODIFIER,
|
||||
theme::{palette::rose_pine::RosePineDawn, prelude::ColorScheme},
|
||||
};
|
||||
|
||||
use bevy::{prelude::*, utils::HashMap};
|
||||
use std::f32::consts::FRAC_PI_2;
|
||||
use strum::IntoEnumIterator;
|
||||
@ -10,15 +16,26 @@ use strum::IntoEnumIterator;
|
||||
const HEX_SIDES: u32 = 6;
|
||||
const WHITE_EMISSION_INTENSITY: f32 = 10.;
|
||||
|
||||
/// Collection of mesh and material assets used in maze rendering.
|
||||
///
|
||||
/// This struct contains all the necessary assets for rendering maze components,
|
||||
/// including hexagonal tiles, walls, and custom colored materials.
|
||||
#[derive(Debug)]
|
||||
pub struct MazeAssets {
|
||||
/// Mesh for hexagonal floor tiles
|
||||
pub hex_mesh: Handle<Mesh>,
|
||||
/// Mesh for wall segments
|
||||
pub wall_mesh: Handle<Mesh>,
|
||||
/// Default material for hexagonal tiles
|
||||
pub hex_material: Handle<StandardMaterial>,
|
||||
/// Default material for walls
|
||||
pub wall_material: Handle<StandardMaterial>,
|
||||
/// Custom materials mapped to specific colors from the RosePineDawn palette
|
||||
pub custom_materials: HashMap<RosePineDawn, Handle<StandardMaterial>>,
|
||||
}
|
||||
|
||||
impl MazeAssets {
|
||||
/// Creates a new instance of MazeAssets with all necessary meshes and materials.
|
||||
pub fn new(
|
||||
meshes: &mut ResMut<Assets<Mesh>>,
|
||||
materials: &mut ResMut<Assets<StandardMaterial>>,
|
||||
@ -43,6 +60,7 @@ impl MazeAssets {
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a hexagonal mesh for floor tiles.
|
||||
fn generate_hex_mesh(radius: f32, depth: f32) -> Mesh {
|
||||
let hexagon = RegularPolygon {
|
||||
sides: HEX_SIDES,
|
||||
@ -54,6 +72,7 @@ fn generate_hex_mesh(radius: f32, depth: f32) -> Mesh {
|
||||
Mesh::from(prism_shape).rotated_by(rotation)
|
||||
}
|
||||
|
||||
/// Generates a square mesh for wall segments.
|
||||
fn generate_square_mesh(depth: f32, wall_size: f32) -> Mesh {
|
||||
let square = Rectangle::new(wall_size, wall_size);
|
||||
let rectangular_prism = Extrusion::new(square, depth);
|
||||
@ -62,6 +81,7 @@ fn generate_square_mesh(depth: f32, wall_size: f32) -> Mesh {
|
||||
Mesh::from(rectangular_prism).rotated_by(rotation)
|
||||
}
|
||||
|
||||
/// Creates a glowing white material for default tile appearance.
|
||||
pub fn white_material() -> StandardMaterial {
|
||||
StandardMaterial {
|
||||
emissive: LinearRgba::new(
|
||||
|
||||
@ -1,6 +1,11 @@
|
||||
//! Maze components and configuration.
|
||||
//!
|
||||
//! 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 crate::floor::components::Floor;
|
||||
|
||||
use super::GlobalMazeConfig;
|
||||
use bevy::prelude::*;
|
||||
use hexlab::Maze;
|
||||
use hexx::{Hex, HexLayout, HexOrientation};
|
||||
@ -19,17 +24,27 @@ pub struct Tile;
|
||||
#[reflect(Component)]
|
||||
pub struct Wall;
|
||||
|
||||
/// Configuration for a single maze instance.
|
||||
///
|
||||
/// Contains all necessary parameters to generate and position a maze,
|
||||
/// including its size, start/end positions, random seed, and layout.
|
||||
#[derive(Debug, Reflect, Component, Clone)]
|
||||
#[reflect(Component)]
|
||||
pub struct MazeConfig {
|
||||
/// Radius of the hexagonal maze
|
||||
pub radius: u16,
|
||||
/// Starting position in hex coordinates
|
||||
pub start_pos: Hex,
|
||||
/// Ending position in hex coordinates
|
||||
pub end_pos: Hex,
|
||||
/// Random seed for maze generation
|
||||
pub seed: u64,
|
||||
/// Layout configuration for hex-to-world space conversion
|
||||
pub layout: HexLayout,
|
||||
}
|
||||
|
||||
impl MazeConfig {
|
||||
/// Creates a new maze configuration with the specified parameters.
|
||||
fn new(
|
||||
radius: u16,
|
||||
orientation: HexOrientation,
|
||||
@ -71,6 +86,7 @@ impl MazeConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates the maze configuration with new global settings.
|
||||
pub fn update(&mut self, global_conig: &GlobalMazeConfig) {
|
||||
self.layout.hex_size = Vec2::splat(global_conig.hex_size);
|
||||
}
|
||||
@ -88,6 +104,10 @@ impl Default for MazeConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a random position within a hexagonal radius.
|
||||
///
|
||||
/// # Returns
|
||||
/// A valid Hex coordinate within the specified radius
|
||||
fn generate_pos<R: Rng>(radius: u16, rng: &mut R) -> Hex {
|
||||
let radius = radius as i32;
|
||||
loop {
|
||||
|
||||
@ -1,10 +1,23 @@
|
||||
use crate::maze::{
|
||||
components::MazeConfig,
|
||||
errors::{MazeError, MazeResult},
|
||||
};
|
||||
//! Common maze generation utilities.
|
||||
use crate::maze::{components::MazeConfig, errors::MazeError};
|
||||
use hexlab::prelude::*;
|
||||
|
||||
pub fn generate_maze(config: &MazeConfig) -> MazeResult<Maze> {
|
||||
/// Generates a new maze based on the provided configuration.
|
||||
///
|
||||
/// This function uses a recursive backtracking algorithm to generate
|
||||
/// a hexagonal maze with the specified parameters.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `config` - Configuration parameters for maze generation including radius and seed.
|
||||
///
|
||||
/// # Returns
|
||||
/// `Result<Maze, MazeError>` - The generated maze or an error if generation fails.
|
||||
///
|
||||
/// # Errors
|
||||
/// Returns `MazeError::GenerationFailed` if:
|
||||
/// - The maze builder fails to create a valid maze
|
||||
/// - The provided radius or seed results in an invalid configuration
|
||||
pub fn generate_maze(config: &MazeConfig) -> Result<Maze, MazeError> {
|
||||
MazeBuilder::new()
|
||||
.with_radius(config.radius)
|
||||
.with_seed(config.seed)
|
||||
|
||||
@ -1,7 +1,13 @@
|
||||
//! Maze despawning functionality.
|
||||
//!
|
||||
//! Module handles the cleanup of maze entities when they need to be removed,
|
||||
//! ensuring proper cleanup of both the maze and all its child entities.
|
||||
use crate::{floor::components::Floor, maze::events::DespawnMaze};
|
||||
|
||||
use bevy::prelude::*;
|
||||
|
||||
pub(super) fn despawn_maze(
|
||||
/// Despawns a maze and all its associated entities for a given floor.
|
||||
pub fn despawn_maze(
|
||||
trigger: Trigger<DespawnMaze>,
|
||||
mut commands: Commands,
|
||||
query: Query<(Entity, &Floor)>,
|
||||
|
||||
@ -1,3 +1,8 @@
|
||||
//! Maze respawning functionality.
|
||||
//!
|
||||
//! Module provides the ability to regenerate mazes for existing floors,
|
||||
//! maintaining the same floor entity but replacing its internal maze structure.
|
||||
|
||||
use super::{common::generate_maze, spawn::spawn_maze_tiles};
|
||||
use crate::{
|
||||
floor::components::Floor,
|
||||
@ -6,7 +11,15 @@ use crate::{
|
||||
use bevy::prelude::*;
|
||||
use hexlab::Maze;
|
||||
|
||||
pub(super) fn respawn_maze(
|
||||
/// Respawns a maze for an existing floor with a new configuration.
|
||||
///
|
||||
/// # Behavior:
|
||||
/// - Finds the target floor
|
||||
/// - Generates a new maze configuration
|
||||
/// - Cleans up existing maze tiles
|
||||
/// - Spawns new maze tiles
|
||||
/// - Updates the floor's configuration
|
||||
pub fn respawn_maze(
|
||||
trigger: Trigger<RespawnMaze>,
|
||||
mut commands: Commands,
|
||||
mut meshes: ResMut<Assets<Mesh>>,
|
||||
|
||||
@ -1,3 +1,7 @@
|
||||
//! Maze spawning and rendering functionality.
|
||||
//!
|
||||
//! Module handles the creation and visualization of hexagonal mazes.
|
||||
|
||||
use super::common::generate_maze;
|
||||
use crate::{
|
||||
constants::FLOOR_Y_OFFSET,
|
||||
@ -20,6 +24,7 @@ use hexlab::prelude::{Tile as HexTile, *};
|
||||
use hexx::HexOrientation;
|
||||
use std::f32::consts::{FRAC_PI_2, FRAC_PI_3, FRAC_PI_6};
|
||||
|
||||
/// Spawns a new maze for the specified floor on [`SpawnMaze`] event.
|
||||
pub fn spawn_maze(
|
||||
trigger: Trigger<SpawnMaze>,
|
||||
mut commands: Commands,
|
||||
@ -44,9 +49,10 @@ pub fn spawn_maze(
|
||||
}
|
||||
};
|
||||
|
||||
// Calculate vertical offset based on floor number
|
||||
let y_offset = match *floor {
|
||||
1 => 0,
|
||||
_ => FLOOR_Y_OFFSET,
|
||||
1 => 0, // Ground/Initial floor (floor 1) is at y=0
|
||||
_ => FLOOR_Y_OFFSET, // Other floors are offset vertically
|
||||
} as f32;
|
||||
|
||||
let entity = commands
|
||||
@ -60,7 +66,7 @@ pub fn spawn_maze(
|
||||
Visibility::Visible,
|
||||
StateScoped(Screen::Gameplay),
|
||||
))
|
||||
.insert_if(CurrentFloor, || *floor == 1)
|
||||
.insert_if(CurrentFloor, || *floor == 1) // Only floor 1 gets CurrentFloor
|
||||
.id();
|
||||
|
||||
let assets = MazeAssets::new(&mut meshes, &mut materials, &global_config);
|
||||
@ -79,6 +85,7 @@ pub fn spawn_maze(
|
||||
}
|
||||
}
|
||||
|
||||
/// Spawns all tiles for a maze as children of the parent maze entity
|
||||
pub fn spawn_maze_tiles(
|
||||
commands: &mut Commands,
|
||||
parent_entity: Entity,
|
||||
@ -94,6 +101,7 @@ pub fn spawn_maze_tiles(
|
||||
});
|
||||
}
|
||||
|
||||
/// Spawns a single hexagonal tile with appropriate transforms and materials
|
||||
pub(super) fn spawn_single_hex_tile(
|
||||
parent: &mut ChildBuilder,
|
||||
assets: &MazeAssets,
|
||||
@ -107,6 +115,7 @@ pub(super) fn spawn_single_hex_tile(
|
||||
HexOrientation::Flat => Quat::from_rotation_y(FRAC_PI_6), // 30 degrees rotation
|
||||
};
|
||||
|
||||
// Select material based on tile position: start, end, or default
|
||||
let material = match tile.pos() {
|
||||
pos if pos == maze_config.start_pos => assets
|
||||
.custom_materials
|
||||
@ -132,12 +141,14 @@ pub(super) fn spawn_single_hex_tile(
|
||||
.with_children(|parent| spawn_walls(parent, assets, tile.walls(), global_config));
|
||||
}
|
||||
|
||||
/// Spawns walls around a hexagonal tile based on the walls configuration
|
||||
fn spawn_walls(
|
||||
parent: &mut ChildBuilder,
|
||||
assets: &MazeAssets,
|
||||
walls: &Walls,
|
||||
global_config: &GlobalMazeConfig,
|
||||
) {
|
||||
// Base rotation for wall alignment (90 degrees counter-clockwise)
|
||||
let z_rotation = Quat::from_rotation_z(-FRAC_PI_2);
|
||||
let y_offset = global_config.height / 2.;
|
||||
|
||||
@ -146,12 +157,25 @@ fn spawn_walls(
|
||||
continue;
|
||||
}
|
||||
|
||||
// Calculate the angle for this wall
|
||||
// FRAC_PI_3 = 60 deg
|
||||
// Negative because going clockwise
|
||||
// i * 60 produces: 0, 60, 120, 180, 240, 300
|
||||
let wall_angle = -FRAC_PI_3 * i as f32;
|
||||
|
||||
// cos(angle) gives x coordinate on unit circle
|
||||
// sin(angle) gives z coordinate on unit circle
|
||||
// Multiply by wall_offset to get actual distance from center
|
||||
let x_offset = global_config.wall_offset() * f32::cos(wall_angle);
|
||||
let z_offset = global_config.wall_offset() * f32::sin(wall_angle);
|
||||
|
||||
// x: distance along x-axis from center
|
||||
// y: vertical offset from center
|
||||
// z: distance along z-axis from center
|
||||
let pos = Vec3::new(x_offset, y_offset, z_offset);
|
||||
|
||||
// 1. Rotate around x-axis to align wall with angle
|
||||
// 2. Add FRAC_PI_2 (90) to make wall perpendicular to angle
|
||||
let x_rotation = Quat::from_rotation_x(wall_angle + FRAC_PI_2);
|
||||
let final_rotation = z_rotation * x_rotation;
|
||||
|
||||
@ -159,6 +183,7 @@ fn spawn_walls(
|
||||
}
|
||||
}
|
||||
|
||||
/// Spawns a single wall segment with the specified rotation and position
|
||||
fn spawn_single_wall(parent: &mut ChildBuilder, assets: &MazeAssets, rotation: Quat, offset: Vec3) {
|
||||
parent.spawn((
|
||||
Name::new("Wall"),
|
||||
|
||||
@ -1,13 +1,22 @@
|
||||
//! Player movement system and related utilities.
|
||||
//!
|
||||
//! This module handles smooth player movement between hexagonal tiles,
|
||||
//! including position interpolation and movement completion detection.
|
||||
use crate::{
|
||||
constants::MOVEMENT_THRESHOLD,
|
||||
floor::components::CurrentFloor,
|
||||
maze::components::MazeConfig,
|
||||
player::components::{CurrentPosition, MovementSpeed, MovementTarget, Player},
|
||||
};
|
||||
|
||||
use bevy::prelude::*;
|
||||
use hexx::Hex;
|
||||
|
||||
pub(super) fn player_movement(
|
||||
/// System handles player movement between hexagonal tiles.
|
||||
///
|
||||
/// Smoothly interpolates player position between hexagonal tiles,
|
||||
/// handling movement target acquisition, position updates, and movement completion.
|
||||
pub fn player_movement(
|
||||
time: Res<Time>,
|
||||
mut query: Query<
|
||||
(
|
||||
@ -48,10 +57,12 @@ pub(super) fn player_movement(
|
||||
}
|
||||
}
|
||||
|
||||
/// Determines if the movement should be completed based on proximity to target.
|
||||
fn should_complete_movement(current_pos: Vec3, target_pos: Vec3) -> bool {
|
||||
(target_pos - current_pos).length() < MOVEMENT_THRESHOLD
|
||||
}
|
||||
|
||||
/// Updates the player's position based on movement parameters.
|
||||
fn update_position(
|
||||
transform: &mut Transform,
|
||||
current_pos: Vec3,
|
||||
@ -69,6 +80,7 @@ fn update_position(
|
||||
transform.translation += movement;
|
||||
}
|
||||
|
||||
/// Calculates the world position for a given hex coordinate.
|
||||
fn calculate_target_position(maze_config: &MazeConfig, target_hex: Hex, y: f32) -> Vec3 {
|
||||
let world_pos = maze_config.layout.hex_to_world_pos(target_hex);
|
||||
Vec3::new(world_pos.x, y, world_pos.y)
|
||||
|
||||
@ -1,4 +1,8 @@
|
||||
use bevy::prelude::*;
|
||||
//! Floor transition handling system.
|
||||
//!
|
||||
//! This module manages player transitions between different maze floors,
|
||||
//! handling both ascending and descending movements based on player position
|
||||
//! and input.
|
||||
|
||||
use crate::{
|
||||
floor::{
|
||||
@ -9,6 +13,12 @@ use crate::{
|
||||
player::components::{CurrentPosition, Player},
|
||||
};
|
||||
|
||||
use bevy::prelude::*;
|
||||
|
||||
/// Handles floor transitions when a player reaches start/end positions.
|
||||
///
|
||||
/// System checks if the player is at a valid transition point (start or end position)
|
||||
/// and triggers floor transitions when the appropriate input is received.
|
||||
pub fn handle_floor_transition(
|
||||
mut player_query: Query<&CurrentPosition, With<Player>>,
|
||||
maze_query: Query<(&MazeConfig, &Floor), With<CurrentFloor>>,
|
||||
@ -25,13 +35,13 @@ pub fn handle_floor_transition(
|
||||
};
|
||||
|
||||
for current_hex in player_query.iter_mut() {
|
||||
// Check for ascending
|
||||
// Check for ascending (at end position)
|
||||
if current_hex.0 == config.end_pos {
|
||||
info!("Ascending");
|
||||
event_writer.send(TransitionFloor::Ascend);
|
||||
}
|
||||
|
||||
// Check for descending
|
||||
// Check for descending (at start position, not on first floor)
|
||||
if current_hex.0 == config.start_pos && floor.0 != 1 {
|
||||
info!("Descending");
|
||||
event_writer.send(TransitionFloor::Descend);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user