Navigation cleanup.

This commit is contained in:
Nolan Darilek 2022-08-04 11:25:09 -05:00
parent e7c9da6f91
commit c02f9b21d6

View File

@ -1,4 +1,7 @@
use std::{error::Error, f32::consts::PI, fmt::Debug, hash::Hash, marker::PhantomData};
use std::{
collections::HashMap, error::Error, f32::consts::PI, fmt::Debug, hash::Hash,
marker::PhantomData,
};
use bevy::prelude::*;
use bevy_rapier2d::prelude::*;
@ -50,31 +53,30 @@ impl Default for RotationSpeed {
#[reflect(Component)]
pub struct Speed(pub f32);
#[derive(Component, Clone, Copy, Debug, Default, Reflect)]
#[reflect(Component)]
pub struct Sprinting;
#[derive(Component, Deref, DerefMut)]
struct SnapTimer(Timer);
#[derive(Default, Deref, DerefMut)]
struct Snapping(bool);
impl Default for SnapTimer {
fn default() -> Self {
Self(Timer::from_seconds(0.25, false))
}
}
fn movement_controls<S>(
mut commands: Commands,
config: Res<NavigationConfig<S>>,
time: Res<Time>,
mut snapping: ResMut<Snapping>,
mut query: Query<
(
Entity,
&ActionState<NavigationAction>,
&mut Velocity,
&mut Speed,
&MaxSpeed,
Option<&RotationSpeed>,
&mut Transform,
Option<&Destination>,
),
With<Player>,
>,
snap_timers: Res<HashMap<Entity, SnapTimer>>,
mut query: Query<(
Entity,
&ActionState<NavigationAction>,
&mut Velocity,
&mut Speed,
&MaxSpeed,
Option<&RotationSpeed>,
&mut Transform,
Option<&Destination>,
)>,
exploration_focused: Query<Entity, With<ExplorationFocused>>,
) where
S: 'static + Clone + Debug + Eq + Hash + Send + Sync,
@ -90,50 +92,47 @@ fn movement_controls<S>(
destination,
) in &mut query
{
if **snapping {
if actions.pressed(NavigationAction::Rotate) {
continue;
}
**snapping = false;
continue;
} else {
let sprinting = actions.pressed(NavigationAction::Sprint);
if sprinting {
commands.entity(entity).insert(Sprinting);
} else {
commands.entity(entity).remove::<Sprinting>();
}
let mut cleanup = false;
if actions.pressed(NavigationAction::Move) {
if let Some(pair) = actions.clamped_axis_pair(NavigationAction::Move) {
cleanup = true;
let mut direction = pair.xy();
let strength = direction.length();
if direction.x > 0. {
direction.x *= config.forward_movement_factor;
} else if direction.x < 0. {
direction.x *= config.backward_movement_factor;
}
if direction.y != 0. {
direction.y *= config.strafe_movement_factor;
}
let s = if sprinting {
**max_speed
} else {
**max_speed / config.sprint_movement_factor
};
**speed = s;
direction *= strength;
let mut v = direction * **speed;
v = transform
.compute_matrix()
.transform_vector3(v.extend(0.))
.truncate();
velocity.linvel = v;
}
} else if destination.is_none() {
velocity.linvel = Vec2::ZERO;
let sprinting = actions.pressed(NavigationAction::Sprint);
let mut cleanup = false;
if actions.pressed(NavigationAction::Move) {
if let Some(pair) = actions.clamped_axis_pair(NavigationAction::Move) {
cleanup = true;
let mut direction = pair.xy();
let strength = direction.length();
let forward_backward_movement_factor = if direction.x > 0. {
config.forward_movement_factor
} else if direction.x < 0. {
config.backward_movement_factor
} else {
0.
};
let movement_factor = if direction.x != 0. && direction.y != 0. {
config
.strafe_movement_factor
.min(forward_backward_movement_factor)
} else if direction.y != 0. {
config.strafe_movement_factor
} else {
forward_backward_movement_factor
};
let mut s = if sprinting {
**max_speed
} else {
**max_speed / config.sprint_movement_factor
};
s *= movement_factor;
**speed = s;
let mut v = direction * **speed;
v = transform
.compute_matrix()
.transform_vector3(v.extend(0.))
.truncate();
velocity.linvel = v;
}
} else if destination.is_none() {
velocity.linvel = Vec2::ZERO;
}
if !snap_timers.contains_key(&entity) {
if let Some(rotation_speed) = rotation_speed {
if actions.pressed(NavigationAction::Rotate) {
cleanup = true;
@ -145,22 +144,25 @@ fn movement_controls<S>(
} else {
velocity.angvel = 0.;
}
if cleanup {
commands.entity(entity).remove::<Destination>();
commands.entity(entity).remove::<Exploring>();
for entity in exploration_focused.iter() {
commands.entity(entity).remove::<ExplorationFocused>();
}
} else {
velocity.angvel = 0.;
}
if cleanup {
commands.entity(entity).remove::<Destination>();
commands.entity(entity).remove::<Exploring>();
for entity in exploration_focused.iter() {
commands.entity(entity).remove::<ExplorationFocused>();
}
}
}
}
fn snap<S>(
fn snap(
mut tts: ResMut<Tts>,
mut snapping: ResMut<Snapping>,
mut snap_timers: ResMut<HashMap<Entity, SnapTimer>>,
mut query: Query<
(
Entity,
&ActionState<NavigationAction>,
&mut Transform,
&mut Velocity,
@ -168,33 +170,32 @@ fn snap<S>(
),
With<Player>,
>,
) -> Result<(), Box<dyn Error>>
where
S: 'static + Copy + Debug + Eq + Hash + Send + Sync,
{
for (actions, mut transform, mut velocity, direction) in query.iter_mut() {
) -> Result<(), Box<dyn Error>> {
for (entity, actions, mut transform, mut velocity, direction) in query.iter_mut() {
if actions.just_pressed(NavigationAction::SnapLeft) {
**snapping = true;
println!("snap left");
snap_timers.insert(entity, SnapTimer::default());
transform.rotation = Quat::from_rotation_z(match direction {
CardinalDirection::North => PI,
CardinalDirection::East => PI / 2.,
CardinalDirection::South => 0.,
CardinalDirection::West => PI * 1.5,
CardinalDirection::West => -PI / 2.,
});
velocity.angvel = 0.;
}
if actions.just_pressed(NavigationAction::SnapRight) {
**snapping = true;
println!("Snap right");
snap_timers.insert(entity, SnapTimer::default());
transform.rotation = Quat::from_rotation_z(match direction {
CardinalDirection::North => 0.,
CardinalDirection::East => PI * 1.5,
CardinalDirection::East => -PI / 2.,
CardinalDirection::South => PI,
CardinalDirection::West => PI / 2.,
});
velocity.angvel = 0.;
}
if actions.just_pressed(NavigationAction::SnapCardinal) {
**snapping = true;
snap_timers.insert(entity, SnapTimer::default());
let yaw: Angle = direction.into();
let yaw = yaw.radians();
transform.rotation = Quat::from_rotation_z(yaw);
@ -202,7 +203,7 @@ where
tts.speak(direction.to_string(), true)?;
}
if actions.just_pressed(NavigationAction::SnapReverse) {
**snapping = true;
snap_timers.insert(entity, SnapTimer::default());
transform.rotate(Quat::from_rotation_z(PI));
velocity.angvel = 0.;
}
@ -210,6 +211,13 @@ where
Ok(())
}
fn tick_snap_timers(time: Res<Time>, mut snap_timers: ResMut<HashMap<Entity, SnapTimer>>) {
for timer in snap_timers.values_mut() {
timer.tick(time.delta());
}
snap_timers.retain(|_, v| !v.finished());
}
fn update_direction(
mut commands: Commands,
mut query: Query<
@ -362,14 +370,13 @@ where
.get_resource::<NavigationConfig<S>>()
.unwrap()
.clone();
const SNAP: &str = "SNAP";
app.init_resource::<Snapping>()
app.init_resource::<HashMap<Entity, SnapTimer>>()
.register_type::<MaxSpeed>()
.register_type::<RotationSpeed>()
.register_type::<Sprinting>()
.add_plugin(InputManagerPlugin::<NavigationAction>::default())
.add_system_to_stage(CoreStage::PostUpdate, update_direction)
.add_system_to_stage(CoreStage::PostUpdate, remove_direction)
.add_system(tick_snap_timers)
.add_system(speak_direction.chain(error_handler))
.add_system(add_speed)
.add_system_to_stage(CoreStage::PostUpdate, remove_speed)
@ -377,24 +384,14 @@ where
const MOVEMENT_CONTROLS: &str = "MOVEMENT_CONTROLS";
if config.movement_control_states.is_empty() {
app.add_system(movement_controls::<S>.label(MOVEMENT_CONTROLS))
.add_system(
snap::<S>
.chain(error_handler)
.label(SNAP)
.before(MOVEMENT_CONTROLS),
);
.add_system(snap.chain(error_handler).before(MOVEMENT_CONTROLS));
} else {
let states = config.movement_control_states;
for state in states {
app.add_system_set(
SystemSet::on_update(state)
.with_system(movement_controls::<S>.label(MOVEMENT_CONTROLS))
.with_system(
snap::<S>
.chain(error_handler)
.label(SNAP)
.before(MOVEMENT_CONTROLS),
),
.with_system(snap.chain(error_handler).before(MOVEMENT_CONTROLS)),
);
}
}