From 30d6cf5fba2746bf27e566d60f73d76f3229a71c Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Thu, 12 Dec 2024 17:24:14 +0200 Subject: [PATCH] feat(player): add collision check --- Cargo.lock | 2 - Cargo.toml | 2 +- src/maze/components.rs | 11 +++-- src/maze/mod.rs | 4 +- src/maze/systems/recreation.rs | 10 ++-- src/maze/systems/setup.rs | 9 +++- src/maze/systems/spawn.rs | 6 +-- src/player/components.rs | 29 +++++++----- src/player/mod.rs | 2 +- src/player/systems/input.rs | 85 +++++++++++++++++++++++++++------- src/player/systems/movement.rs | 48 ++++++++++--------- src/player/systems/spawn.rs | 15 +++--- src/screens/gameplay.rs | 13 +++--- 13 files changed, 150 insertions(+), 86 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fed8ef6..6174fc6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2590,8 +2590,6 @@ checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df" [[package]] name = "hexlab" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9414db96618050e085e36c92ed9e87f0140d3a611914764ee73c7c0e4ebaa2de" dependencies = [ "bevy", "hexx", diff --git a/Cargo.toml b/Cargo.toml index a1414b0..ac7d4b5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ tracing = { version = "0.1", features = [ "release_max_level_warn", ] } hexx = { version = "0.19", features = ["bevy_reflect", "grid"] } -hexlab = { version = "0.2", features = ["bevy"] } +hexlab = { path = "../hexlab", features = ["bevy"] } bevy-inspector-egui = { version = "0.28", optional = true } bevy_egui = { version = "0.31", optional = true } thiserror = "2.0" diff --git a/src/maze/components.rs b/src/maze/components.rs index 1d9ccd8..badb2b0 100644 --- a/src/maze/components.rs +++ b/src/maze/components.rs @@ -1,13 +1,18 @@ use bevy::prelude::*; +use hexlab::HexMaze; #[derive(Debug, Reflect, Component)] #[reflect(Component)] -pub(crate) struct MazeFloor(pub(crate) u8); +pub(crate) struct Maze(pub(crate) HexMaze); #[derive(Debug, Reflect, Component)] #[reflect(Component)] -pub(crate) struct MazeTile; +pub(crate) struct Floor(pub(crate) u8); #[derive(Debug, Reflect, Component)] #[reflect(Component)] -pub(crate) struct MazeWall; +pub(crate) struct Tile; + +#[derive(Debug, Reflect, Component)] +#[reflect(Component)] +pub(crate) struct Wall; diff --git a/src/maze/mod.rs b/src/maze/mod.rs index 3ad26fc..34d31a3 100644 --- a/src/maze/mod.rs +++ b/src/maze/mod.rs @@ -1,7 +1,7 @@ use bevy::{ecs::system::RunSystemOnce, prelude::*}; use events::RecreateMazeEvent; mod assets; -mod components; +pub mod components; pub mod events; mod resources; mod systems; @@ -17,5 +17,5 @@ pub(super) fn plugin(app: &mut App) { pub fn spawn_level_command(world: &mut World) { world.insert_resource(MazePluginLoaded); - world.run_system_once(systems::setup::setup); + let _ = world.run_system_once(systems::setup::setup); } diff --git a/src/maze/systems/recreation.rs b/src/maze/systems/recreation.rs index b3a6472..11b37f2 100644 --- a/src/maze/systems/recreation.rs +++ b/src/maze/systems/recreation.rs @@ -1,6 +1,6 @@ use bevy::prelude::*; -use crate::maze::{components::MazeFloor, events::RecreateMazeEvent, MazeConfig}; +use crate::maze::{components::Floor, events::RecreateMazeEvent, MazeConfig}; use super::setup::setup_maze; @@ -9,7 +9,7 @@ pub(crate) fn handle_maze_recreation_event( mut meshes: ResMut>, mut materials: ResMut>, config: Res, - query: Query<(Entity, &MazeFloor)>, + query: Query<(Entity, &Floor)>, mut event_reader: EventReader, ) { for event in event_reader.read() { @@ -18,9 +18,9 @@ pub(crate) fn handle_maze_recreation_event( } } -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 { +fn despawn_floor(commands: &mut Commands, query: &Query<(Entity, &Floor)>, floor_num: u8) { + for (entity, floor) in query.iter() { + if floor.0 == floor_num { commands.entity(entity).despawn_recursive(); } } diff --git a/src/maze/systems/setup.rs b/src/maze/systems/setup.rs index 37b0538..b44f9e8 100644 --- a/src/maze/systems/setup.rs +++ b/src/maze/systems/setup.rs @@ -1,7 +1,11 @@ use bevy::prelude::*; use hexlab::{GeneratorType, MazeBuilder}; -use crate::maze::{assets::MazeAssets, components::MazeFloor, MazeConfig}; +use crate::maze::{ + assets::MazeAssets, + components::{Floor, Maze}, + MazeConfig, +}; use super::spawn::spawn_single_hex_tile; @@ -31,7 +35,8 @@ pub(super) fn setup_maze( commands .spawn(( Name::new("Floor"), - MazeFloor(1), + Maze(maze.clone()), + Floor(1), Transform::from_translation(Vec3::ZERO), Visibility::Visible, )) diff --git a/src/maze/systems/spawn.rs b/src/maze/systems/spawn.rs index 5849088..be9a9d7 100644 --- a/src/maze/systems/spawn.rs +++ b/src/maze/systems/spawn.rs @@ -6,7 +6,7 @@ use hexx::HexOrientation; use crate::maze::{ assets::MazeAssets, - components::{MazeTile, MazeWall}, + components::{Tile, Wall}, MazeConfig, }; @@ -25,7 +25,7 @@ pub(super) fn spawn_single_hex_tile( parent .spawn(( Name::new(format!("Hex {}", tile)), - MazeTile, + Tile, Mesh3d(assets.hex_mesh.clone()), MeshMaterial3d(assets.hex_material.clone()), Transform::from_translation(world_pos).with_rotation(rotation), @@ -58,7 +58,7 @@ fn spawn_walls(parent: &mut ChildBuilder, assets: &MazeAssets, config: &MazeConf fn spawn_single_wall(parent: &mut ChildBuilder, assets: &MazeAssets, rotation: Quat, offset: Vec3) { parent.spawn(( Name::new("Wall"), - MazeWall, + Wall, Mesh3d(assets.wall_mesh.clone()), MeshMaterial3d(assets.wall_material.clone()), Transform::from_translation(offset).with_rotation(rotation), diff --git a/src/player/components.rs b/src/player/components.rs index 060e302..87f7d18 100644 --- a/src/player/components.rs +++ b/src/player/components.rs @@ -1,20 +1,25 @@ use bevy::prelude::*; use hexx::Hex; -#[derive(Component, Debug, Clone, Copy, PartialEq, Reflect)] +#[derive(Debug, Reflect, Component)] #[reflect(Component)] -pub struct Player { - pub speed: f32, - pub current_hex: Hex, - pub target_hex: Option, -} +#[require(CurrentPosition, MovementSpeed, MovementTarget)] +pub struct Player; -impl Default for Player { +#[derive(Debug, Reflect, Component, Deref, DerefMut, Default)] +#[reflect(Component)] +pub struct CurrentPosition(pub Hex); + +#[derive(Debug, Reflect, Component, Deref, DerefMut)] +#[reflect(Component)] +pub struct MovementSpeed(pub f32); + +impl Default for MovementSpeed { fn default() -> Self { - Self { - speed: 50., - current_hex: Hex::ZERO, - target_hex: None, - } + Self(50.) } } + +#[derive(Debug, Reflect, Component, Deref, DerefMut, Default)] +#[reflect(Component)] +pub struct MovementTarget(pub Option); diff --git a/src/player/mod.rs b/src/player/mod.rs index baf5698..7d067d4 100644 --- a/src/player/mod.rs +++ b/src/player/mod.rs @@ -10,5 +10,5 @@ pub(super) fn plugin(app: &mut App) { } pub fn spawn_player_command(world: &mut World) { - world.run_system_once(systems::spawn::spawn_player); + let _ = world.run_system_once(systems::spawn::spawn_player); } diff --git a/src/player/systems/input.rs b/src/player/systems/input.rs index 917699f..6163700 100644 --- a/src/player/systems/input.rs +++ b/src/player/systems/input.rs @@ -1,28 +1,77 @@ -use crate::player::components::Player; +use crate::{ + maze::{ + components::{Floor, Maze}, + MazeConfig, + }, + player::components::{CurrentPosition, MovementTarget, Player}, +}; use bevy::prelude::*; -use hexx::EdgeDirection; +use hexx::{EdgeDirection, HexOrientation}; -const fn create_direction(key: &KeyCode) -> Option { - match key { - KeyCode::KeyD => Some(EdgeDirection::FLAT_SOUTH), - KeyCode::KeyS => Some(EdgeDirection::FLAT_NORTH_EAST), - KeyCode::KeyA => Some(EdgeDirection::FLAT_NORTH), - KeyCode::KeyQ => Some(EdgeDirection::FLAT_NORTH_WEST), - KeyCode::KeyW => Some(EdgeDirection::FLAT_SOUTH_WEST), - KeyCode::KeyE => Some(EdgeDirection::FLAT_SOUTH_EAST), - _ => None, - } +fn create_direction( + input: &ButtonInput, + orientation: &HexOrientation, +) -> Option { + let w = input.pressed(KeyCode::KeyW); + let a = input.pressed(KeyCode::KeyA); + let s = input.pressed(KeyCode::KeyS); + let d = input.pressed(KeyCode::KeyD); + + let direction = match orientation { + HexOrientation::Pointy => { + match (w, a, s, d) { + (true, false, false, false) => Some(EdgeDirection::POINTY_WEST), // W + (false, false, true, false) => Some(EdgeDirection::POINTY_EAST), // S + (false, true, true, false) => Some(EdgeDirection::POINTY_NORTH_EAST), // A+S + (false, false, true, true) => Some(EdgeDirection::POINTY_SOUTH_EAST), // S+D + (true, true, false, false) => Some(EdgeDirection::POINTY_NORTH_WEST), // W+A + (true, false, false, true) => Some(EdgeDirection::POINTY_SOUTH_WEST), // W+D + _ => None, + } + } + HexOrientation::Flat => { + match (w, a, s, d) { + (false, true, false, false) => Some(EdgeDirection::FLAT_NORTH), // A + (false, false, false, true) => Some(EdgeDirection::FLAT_SOUTH), // D + (false, true, true, false) => Some(EdgeDirection::FLAT_NORTH_EAST), // A+S + (false, false, true, true) => Some(EdgeDirection::FLAT_SOUTH_EAST), // S+D + (true, true, false, false) => Some(EdgeDirection::FLAT_NORTH_WEST), // W+A + (true, false, false, true) => Some(EdgeDirection::FLAT_SOUTH_WEST), // W+D + _ => None, + } + } + }?; + Some(direction.rotate_cw(0)) } -pub(super) fn player_input(input: Res>, mut player_query: Query<&mut Player>) { - for mut player in player_query.iter_mut() { - if player.target_hex.is_some() { +pub(super) fn player_input( + input: Res>, + mut player_query: Query<(&mut MovementTarget, &CurrentPosition), With>, + maze_query: Query<(&Maze, &Floor)>, + maze_config: Res, +) { + let Ok((maze, _floor)) = maze_query.get_single() else { + return; + }; + + for (mut target_pos, current_pos) in player_query.iter_mut() { + if target_pos.is_some() { continue; } - if let Some(direction) = input.get_pressed().find_map(|key| create_direction(key)) { - let next_hex = player.current_hex + direction.into_hex(); - player.target_hex = Some(next_hex); + let Some(direction) = create_direction(&input, &maze_config.layout.orientation) else { + continue; + }; + + let Some(tile) = maze.0.get_tile(¤t_pos) else { + continue; + }; + + if tile.walls().contains(direction) { + continue; } + + let next_hex = current_pos.0.neighbor(direction); + target_pos.0 = Some(next_hex); } } diff --git a/src/player/systems/movement.rs b/src/player/systems/movement.rs index 3d607f4..26ec3d2 100644 --- a/src/player/systems/movement.rs +++ b/src/player/systems/movement.rs @@ -1,19 +1,32 @@ -use crate::{maze::MazeConfig, player::components::Player}; +use crate::{ + maze::MazeConfig, + player::components::{CurrentPosition, MovementSpeed, MovementTarget, Player}, +}; use bevy::prelude::*; use hexx::Hex; pub(super) fn player_movement( time: Res