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)]
pub struct NextFloor;
#[derive(Debug, Reflect, Component)]
#[reflect(Component)]
pub struct MovementState {
pub target_y: f32,
pub direction: f32,
}
impl Default for Floor {
fn default() -> Self {
Self(1)

View File

@ -1,6 +1,6 @@
use crate::{
floor::{
components::{CurrentFloor, NextFloor},
components::{CurrentFloor, MovementState, NextFloor},
events::TransitionFloor,
},
maze::{components::Maze, GlobalMazeConfig},
@ -8,45 +8,77 @@ use crate::{
};
use bevy::prelude::*;
const MOVEMENT_THRESHOLD: f32 = 0.001;
pub(super) fn floor_movement(
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>>,
next_query: Query<Entity, With<NextFloor>>,
player_query: Query<&MovementSpeed, With<Player>>,
time: Res<Time>,
global_config: Res<GlobalMazeConfig>,
_global_config: Res<GlobalMazeConfig>,
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() {
let y_offset = match event {
TransitionFloor::Ascend => -global_config.height,
TransitionFloor::Descend => global_config.height,
let direction = match event {
TransitionFloor::Ascend => -1.,
TransitionFloor::Descend => 1.,
};
for (_, mut transforms) in maze_query.iter_mut() {
let target_y = transforms.translation.y + y_offset;
let delta = target_y - transforms.translation.y;
if delta.abs() > 0.001 {
let movement = delta.signum() * movement_distance.min(delta.abs());
transforms.translation.y += movement;
} else {
transforms.translation.y = target_y;
let Some((current_entity, current_y)) = get_floor_info(&maze_query, &current_query) else {
continue;
};
let Some((next_entity, next_y)) = get_floor_info(&maze_query, &next_query) else {
continue;
};
let diff = (current_y - next_y).abs();
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
if let (Ok(current_entity), Ok(next_entity)) =
(current_query.get_single(), next_query.get_single())
{
commands.entity(current_entity).remove::<CurrentFloor>();
commands
.entity(next_entity)
.remove::<NextFloor>()
.insert(CurrentFloor);
update_current_next_floor(&mut commands, current_entity, next_entity);
}
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(next_entity)
.remove::<NextFloor>()
.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 hexx::Hex;
const MOVEMENT_THRESHOLD: f32 = 0.1;
pub(super) fn player_movement(
time: Res<Time>,
mut query: Query<
@ -48,7 +50,7 @@ pub(super) fn player_movement(
}
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(