Compare commits
4 Commits
e7c9da6f91
...
1fb194266c
Author | SHA1 | Date | |
---|---|---|---|
1fb194266c | |||
e1a1522269 | |||
1fcec80e0e | |||
c02f9b21d6 |
|
@ -493,15 +493,13 @@ impl GlobalTransformExt for GlobalTransform {
|
||||||
) -> String {
|
) -> String {
|
||||||
use bevy::math::Vec3Swizzles;
|
use bevy::math::Vec3Swizzles;
|
||||||
let scale = PHYSICS_SCALE.read().unwrap();
|
let scale = PHYSICS_SCALE.read().unwrap();
|
||||||
let (_, rotation, _) = self.to_scale_rotation_translation();
|
|
||||||
let pos1 = Isometry::new(
|
let pos1 = Isometry::new(
|
||||||
(self.translation() / *scale).xy().into(),
|
(self.translation() / *scale).xy().into(),
|
||||||
rotation.to_scaled_axis().z,
|
self.yaw().radians(),
|
||||||
);
|
);
|
||||||
let (_, other_rotation, _) = self.to_scale_rotation_translation();
|
|
||||||
let pos2 = Isometry::new(
|
let pos2 = Isometry::new(
|
||||||
(other.translation() / *scale).xy().into(),
|
(other.translation() / *scale).xy().into(),
|
||||||
other_rotation.to_scaled_axis().z,
|
other.yaw().radians(),
|
||||||
);
|
);
|
||||||
let closest =
|
let closest =
|
||||||
closest_points(&pos1, &*collider.raw, &pos2, &*other_collider.raw, f32::MAX).unwrap();
|
closest_points(&pos1, &*collider.raw, &pos2, &*other_collider.raw, f32::MAX).unwrap();
|
||||||
|
|
|
@ -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::prelude::*;
|
||||||
use bevy_rapier2d::prelude::*;
|
use bevy_rapier2d::prelude::*;
|
||||||
|
@ -50,31 +53,30 @@ impl Default for RotationSpeed {
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct Speed(pub f32);
|
pub struct Speed(pub f32);
|
||||||
|
|
||||||
#[derive(Component, Clone, Copy, Debug, Default, Reflect)]
|
#[derive(Component, Deref, DerefMut)]
|
||||||
#[reflect(Component)]
|
struct SnapTimer(Timer);
|
||||||
pub struct Sprinting;
|
|
||||||
|
|
||||||
#[derive(Default, Deref, DerefMut)]
|
impl Default for SnapTimer {
|
||||||
struct Snapping(bool);
|
fn default() -> Self {
|
||||||
|
Self(Timer::from_seconds(0.25, false))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn movement_controls<S>(
|
fn movement_controls<S>(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
config: Res<NavigationConfig<S>>,
|
config: Res<NavigationConfig<S>>,
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
mut snapping: ResMut<Snapping>,
|
snap_timers: Res<HashMap<Entity, SnapTimer>>,
|
||||||
mut query: Query<
|
mut query: Query<(
|
||||||
(
|
Entity,
|
||||||
Entity,
|
&ActionState<NavigationAction>,
|
||||||
&ActionState<NavigationAction>,
|
&mut Velocity,
|
||||||
&mut Velocity,
|
&mut Speed,
|
||||||
&mut Speed,
|
&MaxSpeed,
|
||||||
&MaxSpeed,
|
Option<&RotationSpeed>,
|
||||||
Option<&RotationSpeed>,
|
&mut Transform,
|
||||||
&mut Transform,
|
Option<&Destination>,
|
||||||
Option<&Destination>,
|
)>,
|
||||||
),
|
|
||||||
With<Player>,
|
|
||||||
>,
|
|
||||||
exploration_focused: Query<Entity, With<ExplorationFocused>>,
|
exploration_focused: Query<Entity, With<ExplorationFocused>>,
|
||||||
) where
|
) where
|
||||||
S: 'static + Clone + Debug + Eq + Hash + Send + Sync,
|
S: 'static + Clone + Debug + Eq + Hash + Send + Sync,
|
||||||
|
@ -90,50 +92,46 @@ fn movement_controls<S>(
|
||||||
destination,
|
destination,
|
||||||
) in &mut query
|
) in &mut query
|
||||||
{
|
{
|
||||||
if **snapping {
|
let sprinting = actions.pressed(NavigationAction::Sprint);
|
||||||
if actions.pressed(NavigationAction::Rotate) {
|
let mut cleanup = false;
|
||||||
continue;
|
if actions.pressed(NavigationAction::Move) {
|
||||||
}
|
if let Some(pair) = actions.clamped_axis_pair(NavigationAction::Move) {
|
||||||
**snapping = false;
|
cleanup = true;
|
||||||
continue;
|
let direction = pair.xy();
|
||||||
} else {
|
let forward_backward_movement_factor = if direction.x > 0. {
|
||||||
let sprinting = actions.pressed(NavigationAction::Sprint);
|
config.forward_movement_factor
|
||||||
if sprinting {
|
} else if direction.x < 0. {
|
||||||
commands.entity(entity).insert(Sprinting);
|
config.backward_movement_factor
|
||||||
} else {
|
} else {
|
||||||
commands.entity(entity).remove::<Sprinting>();
|
0.
|
||||||
}
|
};
|
||||||
let mut cleanup = false;
|
let movement_factor = if direction.x != 0. && direction.y != 0. {
|
||||||
if actions.pressed(NavigationAction::Move) {
|
config
|
||||||
if let Some(pair) = actions.clamped_axis_pair(NavigationAction::Move) {
|
.strafe_movement_factor
|
||||||
cleanup = true;
|
.min(forward_backward_movement_factor)
|
||||||
let mut direction = pair.xy();
|
} else if direction.y != 0. {
|
||||||
let strength = direction.length();
|
config.strafe_movement_factor
|
||||||
if direction.x > 0. {
|
} else {
|
||||||
direction.x *= config.forward_movement_factor;
|
forward_backward_movement_factor
|
||||||
} else if direction.x < 0. {
|
};
|
||||||
direction.x *= config.backward_movement_factor;
|
let mut s = if sprinting {
|
||||||
}
|
**max_speed
|
||||||
if direction.y != 0. {
|
} else {
|
||||||
direction.y *= config.strafe_movement_factor;
|
**max_speed / config.sprint_movement_factor
|
||||||
}
|
};
|
||||||
let s = if sprinting {
|
s *= movement_factor;
|
||||||
**max_speed
|
**speed = s;
|
||||||
} else {
|
let mut v = direction * **speed;
|
||||||
**max_speed / config.sprint_movement_factor
|
v = transform
|
||||||
};
|
.compute_matrix()
|
||||||
**speed = s;
|
.transform_vector3(v.extend(0.))
|
||||||
direction *= strength;
|
.truncate();
|
||||||
let mut v = direction * **speed;
|
velocity.linvel = v;
|
||||||
v = transform
|
|
||||||
.compute_matrix()
|
|
||||||
.transform_vector3(v.extend(0.))
|
|
||||||
.truncate();
|
|
||||||
velocity.linvel = v;
|
|
||||||
}
|
|
||||||
} else if destination.is_none() {
|
|
||||||
velocity.linvel = Vec2::ZERO;
|
|
||||||
}
|
}
|
||||||
|
} else if destination.is_none() {
|
||||||
|
velocity.linvel = Vec2::ZERO;
|
||||||
|
}
|
||||||
|
if !snap_timers.contains_key(&entity) {
|
||||||
if let Some(rotation_speed) = rotation_speed {
|
if let Some(rotation_speed) = rotation_speed {
|
||||||
if actions.pressed(NavigationAction::Rotate) {
|
if actions.pressed(NavigationAction::Rotate) {
|
||||||
cleanup = true;
|
cleanup = true;
|
||||||
|
@ -145,22 +143,25 @@ fn movement_controls<S>(
|
||||||
} else {
|
} else {
|
||||||
velocity.angvel = 0.;
|
velocity.angvel = 0.;
|
||||||
}
|
}
|
||||||
if cleanup {
|
} else {
|
||||||
commands.entity(entity).remove::<Destination>();
|
velocity.angvel = 0.;
|
||||||
commands.entity(entity).remove::<Exploring>();
|
}
|
||||||
for entity in exploration_focused.iter() {
|
if cleanup {
|
||||||
commands.entity(entity).remove::<ExplorationFocused>();
|
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 tts: ResMut<Tts>,
|
||||||
mut snapping: ResMut<Snapping>,
|
mut snap_timers: ResMut<HashMap<Entity, SnapTimer>>,
|
||||||
mut query: Query<
|
mut query: Query<
|
||||||
(
|
(
|
||||||
|
Entity,
|
||||||
&ActionState<NavigationAction>,
|
&ActionState<NavigationAction>,
|
||||||
&mut Transform,
|
&mut Transform,
|
||||||
&mut Velocity,
|
&mut Velocity,
|
||||||
|
@ -168,33 +169,32 @@ fn snap<S>(
|
||||||
),
|
),
|
||||||
With<Player>,
|
With<Player>,
|
||||||
>,
|
>,
|
||||||
) -> Result<(), Box<dyn Error>>
|
) -> Result<(), Box<dyn Error>> {
|
||||||
where
|
for (entity, actions, mut transform, mut velocity, direction) in query.iter_mut() {
|
||||||
S: 'static + Copy + Debug + Eq + Hash + Send + Sync,
|
|
||||||
{
|
|
||||||
for (actions, mut transform, mut velocity, direction) in query.iter_mut() {
|
|
||||||
if actions.just_pressed(NavigationAction::SnapLeft) {
|
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 {
|
transform.rotation = Quat::from_rotation_z(match direction {
|
||||||
CardinalDirection::North => PI,
|
CardinalDirection::North => PI,
|
||||||
CardinalDirection::East => PI / 2.,
|
CardinalDirection::East => PI / 2.,
|
||||||
CardinalDirection::South => 0.,
|
CardinalDirection::South => 0.,
|
||||||
CardinalDirection::West => PI * 1.5,
|
CardinalDirection::West => -PI / 2.,
|
||||||
});
|
});
|
||||||
velocity.angvel = 0.;
|
velocity.angvel = 0.;
|
||||||
}
|
}
|
||||||
if actions.just_pressed(NavigationAction::SnapRight) {
|
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 {
|
transform.rotation = Quat::from_rotation_z(match direction {
|
||||||
CardinalDirection::North => 0.,
|
CardinalDirection::North => 0.,
|
||||||
CardinalDirection::East => PI * 1.5,
|
CardinalDirection::East => -PI / 2.,
|
||||||
CardinalDirection::South => PI,
|
CardinalDirection::South => PI,
|
||||||
CardinalDirection::West => PI / 2.,
|
CardinalDirection::West => PI / 2.,
|
||||||
});
|
});
|
||||||
velocity.angvel = 0.;
|
velocity.angvel = 0.;
|
||||||
}
|
}
|
||||||
if actions.just_pressed(NavigationAction::SnapCardinal) {
|
if actions.just_pressed(NavigationAction::SnapCardinal) {
|
||||||
**snapping = true;
|
snap_timers.insert(entity, SnapTimer::default());
|
||||||
let yaw: Angle = direction.into();
|
let yaw: Angle = direction.into();
|
||||||
let yaw = yaw.radians();
|
let yaw = yaw.radians();
|
||||||
transform.rotation = Quat::from_rotation_z(yaw);
|
transform.rotation = Quat::from_rotation_z(yaw);
|
||||||
|
@ -202,7 +202,7 @@ where
|
||||||
tts.speak(direction.to_string(), true)?;
|
tts.speak(direction.to_string(), true)?;
|
||||||
}
|
}
|
||||||
if actions.just_pressed(NavigationAction::SnapReverse) {
|
if actions.just_pressed(NavigationAction::SnapReverse) {
|
||||||
**snapping = true;
|
snap_timers.insert(entity, SnapTimer::default());
|
||||||
transform.rotate(Quat::from_rotation_z(PI));
|
transform.rotate(Quat::from_rotation_z(PI));
|
||||||
velocity.angvel = 0.;
|
velocity.angvel = 0.;
|
||||||
}
|
}
|
||||||
|
@ -210,6 +210,13 @@ where
|
||||||
Ok(())
|
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(
|
fn update_direction(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut query: Query<
|
mut query: Query<
|
||||||
|
@ -263,6 +270,14 @@ fn add_speed(mut commands: Commands, query: Query<Entity, (Added<Speed>, Without
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn limit_speed(mut query: Query<(&mut Speed, &MaxSpeed)>) {
|
||||||
|
for (mut speed, max_speed) in &mut query {
|
||||||
|
if **speed > **max_speed {
|
||||||
|
**speed = **max_speed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn remove_speed(removed: RemovedComponents<Speed>, mut query: Query<&mut Velocity>) {
|
fn remove_speed(removed: RemovedComponents<Speed>, mut query: Query<&mut Velocity>) {
|
||||||
for entity in removed.iter() {
|
for entity in removed.iter() {
|
||||||
if let Ok(mut velocity) = query.get_mut(entity) {
|
if let Ok(mut velocity) = query.get_mut(entity) {
|
||||||
|
@ -362,39 +377,29 @@ where
|
||||||
.get_resource::<NavigationConfig<S>>()
|
.get_resource::<NavigationConfig<S>>()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.clone();
|
.clone();
|
||||||
const SNAP: &str = "SNAP";
|
app.init_resource::<HashMap<Entity, SnapTimer>>()
|
||||||
app.init_resource::<Snapping>()
|
|
||||||
.register_type::<MaxSpeed>()
|
.register_type::<MaxSpeed>()
|
||||||
.register_type::<RotationSpeed>()
|
.register_type::<RotationSpeed>()
|
||||||
.register_type::<Sprinting>()
|
|
||||||
.add_plugin(InputManagerPlugin::<NavigationAction>::default())
|
.add_plugin(InputManagerPlugin::<NavigationAction>::default())
|
||||||
.add_system_to_stage(CoreStage::PostUpdate, update_direction)
|
.add_system_to_stage(CoreStage::PreUpdate, update_direction)
|
||||||
.add_system_to_stage(CoreStage::PostUpdate, remove_direction)
|
.add_system_to_stage(CoreStage::PostUpdate, remove_direction)
|
||||||
|
.add_system(tick_snap_timers)
|
||||||
.add_system(speak_direction.chain(error_handler))
|
.add_system(speak_direction.chain(error_handler))
|
||||||
.add_system(add_speed)
|
.add_system(add_speed)
|
||||||
|
.add_system(limit_speed)
|
||||||
.add_system_to_stage(CoreStage::PostUpdate, remove_speed)
|
.add_system_to_stage(CoreStage::PostUpdate, remove_speed)
|
||||||
.add_system_to_stage(CoreStage::PostUpdate, log_area_descriptions::<S, A>);
|
.add_system_to_stage(CoreStage::PostUpdate, log_area_descriptions::<S, A>);
|
||||||
const MOVEMENT_CONTROLS: &str = "MOVEMENT_CONTROLS";
|
const MOVEMENT_CONTROLS: &str = "MOVEMENT_CONTROLS";
|
||||||
if config.movement_control_states.is_empty() {
|
if config.movement_control_states.is_empty() {
|
||||||
app.add_system(movement_controls::<S>.label(MOVEMENT_CONTROLS))
|
app.add_system(movement_controls::<S>.label(MOVEMENT_CONTROLS))
|
||||||
.add_system(
|
.add_system(snap.chain(error_handler).before(MOVEMENT_CONTROLS));
|
||||||
snap::<S>
|
|
||||||
.chain(error_handler)
|
|
||||||
.label(SNAP)
|
|
||||||
.before(MOVEMENT_CONTROLS),
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
let states = config.movement_control_states;
|
let states = config.movement_control_states;
|
||||||
for state in states {
|
for state in states {
|
||||||
app.add_system_set(
|
app.add_system_set(
|
||||||
SystemSet::on_update(state)
|
SystemSet::on_update(state)
|
||||||
.with_system(movement_controls::<S>.label(MOVEMENT_CONTROLS))
|
.with_system(movement_controls::<S>.label(MOVEMENT_CONTROLS))
|
||||||
.with_system(
|
.with_system(snap.chain(error_handler).before(MOVEMENT_CONTROLS)),
|
||||||
snap::<S>
|
|
||||||
.chain(error_handler)
|
|
||||||
.label(SNAP)
|
|
||||||
.before(MOVEMENT_CONTROLS),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user