From 04a7c1b503ad8bf42419cf3e2b765a9ba93168d4 Mon Sep 17 00:00:00 2001 From: "Earthmark (Daniel Miller)" Date: Tue, 19 Apr 2022 23:38:44 -0700 Subject: [PATCH 01/16] Got axis rotation on world change working. --- Cargo.toml | 4 +- index.html | 7 ++ src/level/input.rs | 78 ++++++------- src/level/loader.rs | 6 +- src/level/maze_level.rs | 24 +++- src/level/maze_renderer.rs | 221 ++++++++++++++++++++++++++++++------- src/level/plugin.rs | 11 +- 7 files changed, 263 insertions(+), 88 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index af59c92..6608325 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,8 +5,8 @@ name = "nothing-moves" version = "0.1.0" [dependencies] -bevy = "0.7" -rand = "0.8" +bevy = "*" +rand = "*" # Enable only a small amount of optimization in debug mode [profile.dev] diff --git a/index.html b/index.html index e69de29..9307c15 100644 --- a/index.html +++ b/index.html @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/src/level/input.rs b/src/level/input.rs index 885c375..c52fb56 100644 --- a/src/level/input.rs +++ b/src/level/input.rs @@ -4,51 +4,43 @@ use super::maze_level::*; use super::maze_level::{Axis, Direction}; pub fn level_navigation( - level: Option>, + mut level: ResMut, keys: Res>, mut position_event: EventWriter, mut axis_event: EventWriter, ) { - if let Some(mut level) = level { - if keys.just_pressed(KeyCode::Q) { - level.shift_axis(Axis::X, Direction::Negative); - axis_event.send(AxisChanged { axis: level.axis() }); - } - if keys.just_pressed(KeyCode::E) { - level.shift_axis(Axis::X, Direction::Positive); - axis_event.send(AxisChanged { axis: level.axis() }); - } - if keys.just_pressed(KeyCode::Z) { - level.shift_axis(Axis::Y, Direction::Negative); - axis_event.send(AxisChanged { axis: level.axis() }); - } - if keys.just_pressed(KeyCode::X) { - level.shift_axis(Axis::Y, Direction::Positive); - axis_event.send(AxisChanged { axis: level.axis() }); - } - if keys.just_pressed(KeyCode::W) { - level.move_pos(Axis::X, Direction::Positive); - position_event.send(PositionChanged { - position: level.pos(), - }); - } - if keys.just_pressed(KeyCode::S) { - level.move_pos(Axis::X, Direction::Negative); - position_event.send(PositionChanged { - position: level.pos(), - }); - } - if keys.just_pressed(KeyCode::D) { - level.move_pos(Axis::Y, Direction::Positive); - position_event.send(PositionChanged { - position: level.pos(), - }); - } - if keys.just_pressed(KeyCode::A) { - level.move_pos(Axis::Y, Direction::Negative); - position_event.send(PositionChanged { - position: level.pos(), - }); - } - } + let mut shift_axis = |key: KeyCode, axis: Axis, dir: Direction| { + if keys.just_pressed(key) { + let previous_axis = level.axis(); + level.shift_axis(axis, dir); + let axis = level.axis(); + if previous_axis != axis { + axis_event.send(AxisChanged { + axis, + previous_axis, + }); + } + } + }; + shift_axis(KeyCode::Q, Axis::X, Direction::Negative); + shift_axis(KeyCode::E, Axis::X, Direction::Positive); + shift_axis(KeyCode::Z, Axis::Y, Direction::Negative); + shift_axis(KeyCode::X, Axis::Y, Direction::Positive); + let mut shift_position = |key: KeyCode, axis: Axis, dir: Direction| { + if keys.just_pressed(key) { + let previous_position = level.pos(); + level.move_pos(axis, dir); + let position = level.pos(); + if previous_position != position { + position_event.send(PositionChanged { + position, + previous_position, + }); + } + } + }; + shift_position(KeyCode::W, Axis::X, Direction::Positive); + shift_position(KeyCode::S, Axis::X, Direction::Negative); + shift_position(KeyCode::D, Axis::Y, Direction::Positive); + shift_position(KeyCode::A, Axis::Y, Direction::Negative); } diff --git a/src/level/loader.rs b/src/level/loader.rs index afb7d26..721bfaf 100644 --- a/src/level/loader.rs +++ b/src/level/loader.rs @@ -65,8 +65,12 @@ pub fn initial_events_on_load( ) { position_changed.send(PositionChanged { position: maze.pos(), + previous_position: maze.pos(), + }); + axis_changed.send(AxisChanged { + axis: maze.axis(), + previous_axis: maze.axis(), }); - axis_changed.send(AxisChanged { axis: maze.axis() }); } pub fn load_maze_assets( diff --git a/src/level/maze_level.rs b/src/level/maze_level.rs index f2875b6..ed8fdf7 100644 --- a/src/level/maze_level.rs +++ b/src/level/maze_level.rs @@ -11,11 +11,13 @@ struct MazeImpl { #[derive(Clone, Debug)] pub struct AxisChanged { pub axis: [u8; 2], + pub previous_axis: [u8; 2], } #[derive(Clone, Debug)] pub struct PositionChanged { pub position: [u8; 2], + pub previous_position: [u8; 2], } #[derive(PartialEq, Eq, Clone, Copy)] @@ -56,8 +58,16 @@ impl Direction { fn shift_wrapped(&self, value: u8, limit: u8) -> u8 { (match self { Direction::Positive => value.checked_add(1).unwrap_or(0), - Direction::Negative => value.checked_sub(1).unwrap_or(limit - 2), - } % (limit - 1)) + Direction::Negative => value.checked_sub(1).unwrap_or(limit - 1), + } % limit) + } + + fn shift_clamped(&self, value: u8, limit: u8) -> u8 { + match self { + Direction::Positive => value.checked_add(1).unwrap_or(limit - 1), + Direction::Negative => value.checked_sub(1).unwrap_or(0), + } + .clamp(0, limit - 1) } } @@ -96,7 +106,7 @@ impl MazeView for MazeImpl { target_axis }; - let new_off_axis = dir.shift_wrapped(linear_current, DIMS as u8); + let new_off_axis = dir.shift_clamped(linear_current, DIMS as u8 - 1); let dest = if new_off_axis >= off_target_axis { new_off_axis + 1 } else { @@ -129,6 +139,13 @@ impl MazeView for MazeImpl { ] } + fn pos_in(&self, axis: [u8; 2]) -> [u8; 2] { + [ + self.position[axis[0] as usize], + self.position[axis[1] as usize], + ] + } + fn move_pos(&mut self, axis: Axis, dir: Direction) { let dim = *axis.get(&self.axis) as usize; if let Some(true) = self.can_move(dim as u8, dir) { @@ -175,6 +192,7 @@ pub trait MazeView: Sync + Send { fn dims(&self) -> &[u8]; fn pos_limit(&self) -> [u8; 2]; fn pos(&self) -> [u8; 2]; + fn pos_in(&self, axis: [u8; 2]) -> [u8; 2]; fn move_pos(&mut self, axis: Axis, dir: Direction); fn can_move(&self, dim: u8, dir: Direction) -> Option; diff --git a/src/level/maze_renderer.rs b/src/level/maze_renderer.rs index f6fc42d..3a9549b 100644 --- a/src/level/maze_renderer.rs +++ b/src/level/maze_renderer.rs @@ -1,38 +1,35 @@ -use std::f32::consts::PI; +use std::time::{Duration, Instant}; +use std::{f32::consts::PI, marker::PhantomData}; use super::{loader::MazeAssets, maze_level::*}; use bevy::prelude::*; -pub fn spawn_maze_root(mut c: Commands) { - c.spawn_bundle(MazeRendererBundle { - renderer: MazeRenderer { last_axis: [0, 0] }, - transform: Default::default(), - global_transform: Default::default(), - }); -} - -#[derive(Bundle)] -pub struct MazeRendererBundle { - pub renderer: MazeRenderer, +#[derive(Bundle, Default)] +pub struct MazePositionTrackerBundle { + pub position_tracker: MazePositionTracker, pub transform: Transform, pub global_transform: GlobalTransform, } -#[derive(Component)] -pub struct MazeRenderer { - last_axis: [u8; 2], +#[derive(Component, Default)] +pub struct MazePositionTracker { + visible_axis: [u8; 2], +} + +fn maze_level_offset(maze: &MazeLevel, axis: [u8; 2]) -> Vec3 { + let p = maze.pos_in(axis); + Vec3::new(-(p[0] as f32), 0.0, -(p[1] as f32)) } pub fn update_maze_offset( level: Res, - mut maze_query: Query<(&MazeRenderer, &mut Transform)>, + mut maze_query: Query<(&MazePositionTracker, &mut Transform)>, mut position_changed: EventReader, mut axis_changed: EventReader, ) { let mut update_pos = || { - for (_, mut trs) in maze_query.iter_mut() { - let p = level.pos(); - trs.translation = Vec3::new(-(p[0] as f32), 0.0, -(p[1] as f32)) + for (renderer, mut trs) in maze_query.iter_mut() { + trs.translation = maze_level_offset(level.as_ref(), renderer.visible_axis); } }; for _ in position_changed.iter() { @@ -43,48 +40,102 @@ pub fn update_maze_offset( } } +#[derive(Bundle, Default)] +pub struct MazeRotationTrackerBundle { + pub position_tracker: MazeRotationTracker, + pub transform: Transform, + pub global_transform: GlobalTransform, +} + +#[derive(Component, Default)] +pub struct MazeRotationTracker { + visible_axis: [u8; 2], +} + +// The maze hierarchy is as follows: +// - Rotate - (player assumed to be in the center) +// - Player Offset / scale - (enforces the player is in the center) +// - Walls + +fn get_rot_from_axis(axis: &AxisChanged) -> Quat { + let length = PI / 2.0; + let x_axis = if axis.axis[0] < axis.previous_axis[0] { + Quat::from_euler(EulerRot::XYZ, 0.0, 0.0, length) + } else if axis.axis[0] > axis.previous_axis[0] { + Quat::from_euler(EulerRot::XYZ, 0.0, 0.0, -length) + } else { + Quat::IDENTITY + }; + let y_axis = if axis.axis[1] < axis.previous_axis[1] { + Quat::from_euler(EulerRot::XYZ, length, 0.0, 0.0) + } else if axis.axis[1] > axis.previous_axis[1] { + Quat::from_euler(EulerRot::XYZ, -length, 0.0, 0.0) + } else { + Quat::IDENTITY + }; + x_axis * y_axis +} + pub fn maze_level_renderer( + time: Res