fix: floor movement

This commit is contained in:
Kristofers Solo 2024-12-23 14:48:46 +02:00
parent 8683f727f2
commit 3659ffa1a6
3 changed files with 68 additions and 27 deletions

View File

@ -12,6 +12,13 @@ pub struct CurrentFloor;
#[reflect(Component)] #[reflect(Component)]
pub struct NextFloor; pub struct NextFloor;
#[derive(Debug, Reflect, Component)]
#[reflect(Component)]
pub struct MovementState {
pub target_y: f32,
pub direction: f32,
}
impl Default for Floor { impl Default for Floor {
fn default() -> Self { fn default() -> Self {
Self(1) Self(1)

View File

@ -1,6 +1,6 @@
use crate::{ use crate::{
floor::{ floor::{
components::{CurrentFloor, NextFloor}, components::{CurrentFloor, MovementState, NextFloor},
events::TransitionFloor, events::TransitionFloor,
}, },
maze::{components::Maze, GlobalMazeConfig}, maze::{components::Maze, GlobalMazeConfig},
@ -8,45 +8,77 @@ use crate::{
}; };
use bevy::prelude::*; use bevy::prelude::*;
const MOVEMENT_THRESHOLD: f32 = 0.001;
pub(super) fn floor_movement( pub(super) fn floor_movement(
mut commands: Commands, mut commands: Commands,
mut maze_query: Query<(Entity, &mut Transform), With<Maze>>, mut maze_query: Query<(Entity, &mut Transform, Option<&mut MovementState>), With<Maze>>,
current_query: Query<Entity, With<CurrentFloor>>, current_query: Query<Entity, With<CurrentFloor>>,
next_query: Query<Entity, With<NextFloor>>, next_query: Query<Entity, With<NextFloor>>,
player_query: Query<&MovementSpeed, With<Player>>, player_query: Query<&MovementSpeed, With<Player>>,
time: Res<Time>, time: Res<Time>,
global_config: Res<GlobalMazeConfig>, _global_config: Res<GlobalMazeConfig>,
mut event_reader: EventReader<TransitionFloor>, mut event_reader: EventReader<TransitionFloor>,
) { ) {
let speed = player_query.get_single().map(|s| s.0).unwrap_or(100.);
let movement_distance = speed * time.delta_secs();
for event in event_reader.read() { for event in event_reader.read() {
let y_offset = match event { let direction = match event {
TransitionFloor::Ascend => -global_config.height, TransitionFloor::Ascend => -1.,
TransitionFloor::Descend => global_config.height, TransitionFloor::Descend => 1.,
}; };
for (_, mut transforms) in maze_query.iter_mut() { let Some((current_entity, current_y)) = get_floor_info(&maze_query, &current_query) else {
let target_y = transforms.translation.y + y_offset; continue;
let delta = target_y - transforms.translation.y; };
if delta.abs() > 0.001 { let Some((next_entity, next_y)) = get_floor_info(&maze_query, &next_query) else {
let movement = delta.signum() * movement_distance.min(delta.abs()); continue;
transforms.translation.y += movement; };
} else { let diff = (current_y - next_y).abs();
transforms.translation.y = target_y;
for (entity, transforms, movement_state) in maze_query.iter_mut() {
let target_y = diff.mul_add(direction, transforms.translation.y);
if movement_state.is_none() {
commands.entity(entity).insert(MovementState {
target_y,
direction,
});
} }
} }
// Update current/next floor update_current_next_floor(&mut commands, current_entity, next_entity);
if let (Ok(current_entity), Ok(next_entity)) = }
(current_query.get_single(), next_query.get_single())
{ let speed = player_query.get_single().map_or(100., |s| s.0);
let movement_distance = speed * time.delta_secs();
for (entity, mut transform, mut movement_state) in maze_query.iter_mut() {
if let Some(state) = movement_state.as_mut() {
let delta = state.target_y - transform.translation.y;
if delta.abs() > MOVEMENT_THRESHOLD {
let movement = delta.signum() * movement_distance.min(delta.abs());
transform.translation.y += movement;
} else {
transform.translation.y = state.target_y;
commands.entity(entity).remove::<MovementState>();
}
}
}
}
fn update_current_next_floor(commands: &mut Commands, current_entity: Entity, next_entity: Entity) {
commands.entity(current_entity).remove::<CurrentFloor>(); commands.entity(current_entity).remove::<CurrentFloor>();
commands commands
.entity(next_entity) .entity(next_entity)
.remove::<NextFloor>() .remove::<NextFloor>()
.insert(CurrentFloor); .insert(CurrentFloor);
} }
}
fn get_floor_info(
maze_query: &Query<(Entity, &mut Transform, Option<&mut MovementState>), With<Maze>>,
query: &Query<Entity, With<impl Component>>,
) -> Option<(Entity, f32)> {
query.get_single().ok().and_then(|entity| {
maze_query
.get(entity)
.ok()
.map(|(_, transform, _)| (entity, transform.translation.y))
})
} }

View File

@ -6,6 +6,8 @@ use crate::{
use bevy::prelude::*; use bevy::prelude::*;
use hexx::Hex; use hexx::Hex;
const MOVEMENT_THRESHOLD: f32 = 0.1;
pub(super) fn player_movement( pub(super) fn player_movement(
time: Res<Time>, time: Res<Time>,
mut query: Query< mut query: Query<
@ -48,7 +50,7 @@ pub(super) fn player_movement(
} }
fn should_complete_movement(current_pos: Vec3, target_pos: Vec3) -> bool { fn should_complete_movement(current_pos: Vec3, target_pos: Vec3) -> bool {
(target_pos - current_pos).length() < 0.1 (target_pos - current_pos).length() < MOVEMENT_THRESHOLD
} }
fn update_position( fn update_position(