Compare commits
No commits in common. "8eb050d10ad0e3f732cb0b95b7f03632e420113e" and "f19beaa73aa0c24c30aae3644192097835ba4c3d" have entirely different histories.
8eb050d10a
...
f19beaa73a
|
@ -20,7 +20,7 @@ bevy_synthizer = "0.7"
|
||||||
bevy_tts = { version = "0.9", default-features = false, features = ["tolk"] }
|
bevy_tts = { version = "0.9", default-features = false, features = ["tolk"] }
|
||||||
coord_2d = "0.3"
|
coord_2d = "0.3"
|
||||||
here_be_dragons = { version = "0.3", features = ["serde"] }
|
here_be_dragons = { version = "0.3", features = ["serde"] }
|
||||||
leafwing-input-manager = "0.15"
|
leafwing-input-manager = "0.14"
|
||||||
maze_generator = "2"
|
maze_generator = "2"
|
||||||
once_cell = "1"
|
once_cell = "1"
|
||||||
pathfinding = "4"
|
pathfinding = "4"
|
||||||
|
|
|
@ -9,7 +9,6 @@ use crate::{
|
||||||
core::{Player, PointLike},
|
core::{Player, PointLike},
|
||||||
error::error_handler,
|
error::error_handler,
|
||||||
map::Map,
|
map::Map,
|
||||||
navigation::NavigationAction,
|
|
||||||
pathfinding::Destination,
|
pathfinding::Destination,
|
||||||
visibility::{RevealedTiles, Viewshed, Visible, VisibleEntities},
|
visibility::{RevealedTiles, Viewshed, Visible, VisibleEntities},
|
||||||
};
|
};
|
||||||
|
@ -355,25 +354,6 @@ where
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cancel_on_navigate(
|
|
||||||
mut commands: Commands,
|
|
||||||
explorers: Query<
|
|
||||||
Entity,
|
|
||||||
(
|
|
||||||
With<ActionState<ExplorationAction>>,
|
|
||||||
Changed<ActionState<NavigationAction>>,
|
|
||||||
),
|
|
||||||
>,
|
|
||||||
focused: Query<Entity, With<ExplorationFocused>>,
|
|
||||||
) {
|
|
||||||
if !explorers.is_empty() {
|
|
||||||
for entity in &focused {
|
|
||||||
println!("Clearing focus");
|
|
||||||
commands.entity(entity).remove::<ExplorationFocused>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cleanup(
|
fn cleanup(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
explorers: Query<Entity, With<Exploring>>,
|
explorers: Query<Entity, With<Exploring>>,
|
||||||
|
@ -418,7 +398,7 @@ where
|
||||||
.register_type::<Explorable>()
|
.register_type::<Explorable>()
|
||||||
.add_plugins(InputManagerPlugin::<ExplorationAction>::default())
|
.add_plugins(InputManagerPlugin::<ExplorationAction>::default())
|
||||||
.add_systems(
|
.add_systems(
|
||||||
FixedUpdate,
|
Update,
|
||||||
(
|
(
|
||||||
exploration_type_change::<ExplorationType>.pipe(error_handler),
|
exploration_type_change::<ExplorationType>.pipe(error_handler),
|
||||||
exploration_type_changed_announcement::<ExplorationType>.pipe(error_handler),
|
exploration_type_changed_announcement::<ExplorationType>.pipe(error_handler),
|
||||||
|
@ -427,7 +407,7 @@ where
|
||||||
.in_set(Exploration),
|
.in_set(Exploration),
|
||||||
)
|
)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
FixedUpdate,
|
Update,
|
||||||
(
|
(
|
||||||
exploration_focus::<MapData>,
|
exploration_focus::<MapData>,
|
||||||
exploration_type_focus::<ExplorationType>.pipe(error_handler),
|
exploration_type_focus::<ExplorationType>.pipe(error_handler),
|
||||||
|
@ -437,14 +417,11 @@ where
|
||||||
.chain()
|
.chain()
|
||||||
.in_set(Exploration),
|
.in_set(Exploration),
|
||||||
)
|
)
|
||||||
.add_systems(
|
.add_systems(Update, navigate_to_explored::<MapData>.in_set(Exploration));
|
||||||
FixedUpdate,
|
|
||||||
(navigate_to_explored::<MapData>, cancel_on_navigate).in_set(Exploration),
|
|
||||||
);
|
|
||||||
if !config.states.is_empty() {
|
if !config.states.is_empty() {
|
||||||
let states = config.states;
|
let states = config.states;
|
||||||
for state in states {
|
for state in states {
|
||||||
app.configure_sets(FixedUpdate, Exploration.run_if(in_state(state.clone())))
|
app.configure_sets(Update, Exploration.run_if(in_state(state.clone())))
|
||||||
.add_systems(OnExit(state), cleanup);
|
.add_systems(OnExit(state), cleanup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,16 +3,17 @@ use std::{collections::HashMap, error::Error, f32::consts::PI, fmt::Debug, hash:
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_rapier2d::prelude::*;
|
use bevy_rapier2d::prelude::*;
|
||||||
use bevy_tts::Tts;
|
use bevy_tts::Tts;
|
||||||
use leafwing_input_manager::prelude::*;
|
use leafwing_input_manager::{axislike::DualAxisData, prelude::*};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
core::{Angle, Area, CardinalDirection, GlobalTransformExt, Player, TransformExt},
|
core::{Angle, Area, CardinalDirection, GlobalTransformExt, Player, TransformExt},
|
||||||
error::error_handler,
|
error::error_handler,
|
||||||
|
exploration::{ExplorationFocused, Exploring},
|
||||||
log::Log,
|
log::Log,
|
||||||
utils::target_and_other,
|
utils::target_and_other,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug, Reflect)]
|
#[derive(Actionlike, PartialEq, Eq, Clone, Copy, Hash, Debug, Reflect)]
|
||||||
pub enum NavigationAction {
|
pub enum NavigationAction {
|
||||||
Move,
|
Move,
|
||||||
Translate,
|
Translate,
|
||||||
|
@ -25,23 +26,6 @@ pub enum NavigationAction {
|
||||||
SnapReverse,
|
SnapReverse,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Actionlike for NavigationAction {
|
|
||||||
fn input_control_kind(&self) -> InputControlKind {
|
|
||||||
match &self {
|
|
||||||
NavigationAction::Move
|
|
||||||
| NavigationAction::Translate
|
|
||||||
| NavigationAction::SetLinearVelocity => InputControlKind::DualAxis,
|
|
||||||
NavigationAction::Rotate | NavigationAction::SetAngularVelocity => {
|
|
||||||
InputControlKind::Axis
|
|
||||||
}
|
|
||||||
NavigationAction::SnapLeft
|
|
||||||
| NavigationAction::SnapRight
|
|
||||||
| NavigationAction::SnapCardinal
|
|
||||||
| NavigationAction::SnapReverse => InputControlKind::Button,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Component, Clone, Copy, Debug, Deref, DerefMut, Reflect)]
|
#[derive(Component, Clone, Copy, Debug, Deref, DerefMut, Reflect)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct BackwardMovementFactor(pub f32);
|
pub struct BackwardMovementFactor(pub f32);
|
||||||
|
@ -151,6 +135,7 @@ fn tick_snap_timers(time: Res<Time>, mut snap_timers: ResMut<SnapTimers>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn controls(
|
fn controls(
|
||||||
|
mut commands: Commands,
|
||||||
rapier_context: Res<RapierContext>,
|
rapier_context: Res<RapierContext>,
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
snap_timers: Res<SnapTimers>,
|
snap_timers: Res<SnapTimers>,
|
||||||
|
@ -166,6 +151,7 @@ fn controls(
|
||||||
&mut Transform,
|
&mut Transform,
|
||||||
&Collider,
|
&Collider,
|
||||||
)>,
|
)>,
|
||||||
|
exploration_focused: Query<Entity, With<ExplorationFocused>>,
|
||||||
) {
|
) {
|
||||||
for (
|
for (
|
||||||
entity,
|
entity,
|
||||||
|
@ -180,13 +166,17 @@ fn controls(
|
||||||
collider,
|
collider,
|
||||||
) in &mut query
|
) in &mut query
|
||||||
{
|
{
|
||||||
if !actions.action_disabled(&NavigationAction::Move) {
|
let mut cleanup = false;
|
||||||
let mut direction = actions.clamped_axis_pair(&NavigationAction::Move);
|
if actions.pressed(&NavigationAction::Move) {
|
||||||
|
if let Some(pair) = actions.clamped_axis_pair(&NavigationAction::Move) {
|
||||||
|
cleanup = true;
|
||||||
|
let mut direction = pair.xy();
|
||||||
let forward_movement_factor =
|
let forward_movement_factor =
|
||||||
forward_movement_factor.map(|v| v.0).unwrap_or_else(|| 1.);
|
forward_movement_factor.map(|v| v.0).unwrap_or_else(|| 1.);
|
||||||
let backward_movement_factor =
|
let backward_movement_factor =
|
||||||
backward_movement_factor.map(|v| v.0).unwrap_or_else(|| 1.);
|
backward_movement_factor.map(|v| v.0).unwrap_or_else(|| 1.);
|
||||||
let strafe_movement_factor = strafe_movement_factor.map(|v| v.0).unwrap_or_else(|| 1.);
|
let strafe_movement_factor =
|
||||||
|
strafe_movement_factor.map(|v| v.0).unwrap_or_else(|| 1.);
|
||||||
let forward_backward_movement_factor = if direction.x > 0. {
|
let forward_backward_movement_factor = if direction.x > 0. {
|
||||||
forward_movement_factor
|
forward_movement_factor
|
||||||
} else if direction.x < 0. {
|
} else if direction.x < 0. {
|
||||||
|
@ -208,20 +198,44 @@ fn controls(
|
||||||
.truncate();
|
.truncate();
|
||||||
let mut speed = **speed;
|
let mut speed = **speed;
|
||||||
speed *= movement_factor;
|
speed *= movement_factor;
|
||||||
let move_velocity = direction * speed;
|
let velocity = direction * speed;
|
||||||
// println!("{entity:?}: SetLinearVelocity: {velocity:?}");
|
// println!("{entity:?}: SetLinearVelocity: {velocity:?}");
|
||||||
actions.set_axis_pair(&NavigationAction::SetLinearVelocity, move_velocity);
|
actions.press(&NavigationAction::SetLinearVelocity);
|
||||||
|
actions
|
||||||
|
.action_data_mut_or_default(&NavigationAction::SetLinearVelocity)
|
||||||
|
.axis_pair = Some(DualAxisData::from_xy(velocity));
|
||||||
}
|
}
|
||||||
if velocity.linvel != actions.axis_pair(&NavigationAction::SetLinearVelocity) {
|
} else if actions.just_released(&NavigationAction::Move) {
|
||||||
velocity.linvel = actions.axis_pair(&NavigationAction::SetLinearVelocity);
|
trace!("{entity:?}: Stopped moving");
|
||||||
|
actions.release(&NavigationAction::SetLinearVelocity);
|
||||||
|
actions.release(&NavigationAction::Translate);
|
||||||
|
actions
|
||||||
|
.action_data_mut_or_default(&NavigationAction::Move)
|
||||||
|
.axis_pair = Some(DualAxisData::from_xy(Vec2::ZERO));
|
||||||
}
|
}
|
||||||
if actions.axis_pair(&NavigationAction::Translate) != Vec2::ZERO {
|
if actions.pressed(&NavigationAction::SetLinearVelocity) {
|
||||||
let pair = actions.axis_pair(&NavigationAction::Translate);
|
if let Some(pair) = actions.axis_pair(&NavigationAction::SetLinearVelocity) {
|
||||||
|
// println!("{entity:?}: SetLinearVelocity: {pair:?}");
|
||||||
|
velocity.linvel = pair.into();
|
||||||
|
} else {
|
||||||
|
// println!("{entity:?}: SetLinearVelocity: 0");
|
||||||
|
velocity.linvel = Vec2::ZERO;
|
||||||
|
}
|
||||||
|
} else if actions.just_released(&NavigationAction::SetLinearVelocity) {
|
||||||
|
// println!("{entity:?}: Released velocity");
|
||||||
|
velocity.linvel = Vec2::ZERO;
|
||||||
|
actions
|
||||||
|
.action_data_mut_or_default(&NavigationAction::SetLinearVelocity)
|
||||||
|
.axis_pair = None;
|
||||||
|
}
|
||||||
|
if actions.pressed(&NavigationAction::Translate) {
|
||||||
|
if let Some(pair) = actions.axis_pair(&NavigationAction::Translate) {
|
||||||
|
let vel = pair.xy();
|
||||||
if rapier_context
|
if rapier_context
|
||||||
.cast_shape(
|
.cast_shape(
|
||||||
transform.translation.truncate(),
|
transform.translation.truncate(),
|
||||||
transform.yaw().radians(),
|
transform.yaw().radians(),
|
||||||
pair,
|
vel,
|
||||||
collider,
|
collider,
|
||||||
ShapeCastOptions {
|
ShapeCastOptions {
|
||||||
max_time_of_impact: 1.,
|
max_time_of_impact: 1.,
|
||||||
|
@ -233,23 +247,50 @@ fn controls(
|
||||||
)
|
)
|
||||||
.is_none()
|
.is_none()
|
||||||
{
|
{
|
||||||
transform.translation += pair.extend(0.);
|
transform.translation += vel.extend(0.);
|
||||||
}
|
}
|
||||||
actions.set_axis_pair(&NavigationAction::Translate, Vec2::ZERO);
|
}
|
||||||
|
} else if actions.just_released(&NavigationAction::Translate) {
|
||||||
|
actions
|
||||||
|
.action_data_mut_or_default(&NavigationAction::Translate)
|
||||||
|
.axis_pair = None;
|
||||||
}
|
}
|
||||||
if !snap_timers.contains_key(&entity) {
|
if !snap_timers.contains_key(&entity) {
|
||||||
if let Some(rotation_speed) = rotation_speed {
|
if let Some(rotation_speed) = rotation_speed {
|
||||||
let delta =
|
if actions.pressed(&NavigationAction::Rotate) {
|
||||||
-rotation_speed.radians() * actions.clamped_value(&NavigationAction::Rotate);
|
cleanup = true;
|
||||||
actions.set_value(&NavigationAction::SetAngularVelocity, delta);
|
let delta = -rotation_speed.radians()
|
||||||
|
* actions.clamped_value(&NavigationAction::Rotate);
|
||||||
|
actions.press(&NavigationAction::SetAngularVelocity);
|
||||||
|
actions
|
||||||
|
.action_data_mut_or_default(&NavigationAction::SetAngularVelocity)
|
||||||
|
.value = delta;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if actions.value(&NavigationAction::SetAngularVelocity) != 0. {
|
}
|
||||||
|
if actions.just_released(&NavigationAction::Rotate) {
|
||||||
|
actions.release(&NavigationAction::SetAngularVelocity);
|
||||||
|
actions
|
||||||
|
.action_data_mut_or_default(&NavigationAction::Rotate)
|
||||||
|
.value = 0.;
|
||||||
|
}
|
||||||
|
if actions.pressed(&NavigationAction::SetAngularVelocity) {
|
||||||
// velocity.angvel =
|
// velocity.angvel =
|
||||||
// actions.value(&NavigationAction::SetAngularVelocity);
|
// actions.value(&NavigationAction::SetAngularVelocity);
|
||||||
transform.rotation *= Quat::from_rotation_z(
|
transform.rotation *= Quat::from_rotation_z(
|
||||||
actions.value(&NavigationAction::SetAngularVelocity) * time.delta_seconds(),
|
actions.value(&NavigationAction::SetAngularVelocity) * time.delta_seconds(),
|
||||||
);
|
);
|
||||||
|
} else if actions.just_released(&NavigationAction::SetAngularVelocity) {
|
||||||
|
actions
|
||||||
|
.action_data_mut_or_default(&NavigationAction::SetAngularVelocity)
|
||||||
|
.value = 0.;
|
||||||
|
velocity.angvel = 0.;
|
||||||
|
}
|
||||||
|
if cleanup {
|
||||||
|
commands.entity(entity).remove::<Exploring>();
|
||||||
|
for entity in &exploration_focused {
|
||||||
|
commands.entity(entity).remove::<ExplorationFocused>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -395,17 +436,12 @@ where
|
||||||
.in_set(Movement),
|
.in_set(Movement),
|
||||||
)
|
)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
FixedUpdate,
|
Update,
|
||||||
(tick_snap_timers, speak_direction.pipe(error_handler)),
|
(tick_snap_timers, speak_direction.pipe(error_handler)),
|
||||||
)
|
)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
PostUpdate,
|
PostUpdate,
|
||||||
(remove_direction, log_area_descriptions::<State>),
|
(remove_direction, log_area_descriptions::<State>),
|
||||||
);
|
);
|
||||||
if !self.states.is_empty() {
|
|
||||||
for state in &self.states {
|
|
||||||
app.configure_sets(Update, Movement.run_if(in_state(state.clone())));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use bevy::{
|
use bevy::{
|
||||||
|
ecs::entity::Entities,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
tasks::{futures_lite::future, prelude::*, Task},
|
tasks::{futures_lite::future, prelude::*, Task},
|
||||||
utils::HashMap,
|
utils::HashMap,
|
||||||
|
@ -8,7 +9,7 @@ use bevy_rapier2d::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
rapier::prelude::{ColliderHandle, ColliderSet, QueryPipeline, RigidBodySet},
|
rapier::prelude::{ColliderHandle, ColliderSet, QueryPipeline, RigidBodySet},
|
||||||
};
|
};
|
||||||
use leafwing_input_manager::{plugin::InputManagerSystem, prelude::*};
|
use leafwing_input_manager::{axislike::DualAxisData, plugin::InputManagerSystem, prelude::*};
|
||||||
use pathfinding::prelude::*;
|
use pathfinding::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -20,11 +21,7 @@ use crate::{
|
||||||
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug, Reflect)]
|
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug, Reflect)]
|
||||||
pub struct NegotiatePathAction;
|
pub struct NegotiatePathAction;
|
||||||
|
|
||||||
impl Actionlike for NegotiatePathAction {
|
impl Actionlike for NegotiatePathAction {}
|
||||||
fn input_control_kind(&self) -> InputControlKind {
|
|
||||||
InputControlKind::DualAxis
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Component, Debug, Deref, DerefMut)]
|
#[derive(Component, Debug, Deref, DerefMut)]
|
||||||
struct Calculating(Task<Option<Path>>);
|
struct Calculating(Task<Option<Path>>);
|
||||||
|
@ -48,17 +45,6 @@ pub struct Path(pub Vec<(i32, i32)>);
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct CostMap(pub HashMap<(i32, i32), f32>);
|
pub struct CostMap(pub HashMap<(i32, i32), f32>);
|
||||||
|
|
||||||
#[derive(Bundle, Deref, DerefMut)]
|
|
||||||
pub struct PathfindingControlsBundle(pub ActionState<NegotiatePathAction>);
|
|
||||||
|
|
||||||
impl Default for PathfindingControlsBundle {
|
|
||||||
fn default() -> Self {
|
|
||||||
let mut input: ActionState<NegotiatePathAction> = Default::default();
|
|
||||||
input.disable();
|
|
||||||
Self(input)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find_path<D: 'static + Clone + Default + Send + Sync>(
|
pub fn find_path<D: 'static + Clone + Default + Send + Sync>(
|
||||||
start: &dyn PointLike,
|
start: &dyn PointLike,
|
||||||
destination: &dyn PointLike,
|
destination: &dyn PointLike,
|
||||||
|
@ -175,11 +161,7 @@ fn calculate_path(
|
||||||
>,
|
>,
|
||||||
) {
|
) {
|
||||||
for (entity, handle, destination, coordinates, shape, cost_map) in &query {
|
for (entity, handle, destination, coordinates, shape, cost_map) in &query {
|
||||||
trace
|
|
||||||
!("{entity}: destination: {destination:?}");
|
|
||||||
if coordinates.i32() == **destination {
|
if coordinates.i32() == **destination {
|
||||||
trace
|
|
||||||
!("{entity}: remove1");
|
|
||||||
commands
|
commands
|
||||||
.entity(entity)
|
.entity(entity)
|
||||||
.remove::<Path>()
|
.remove::<Path>()
|
||||||
|
@ -229,8 +211,6 @@ fn calculate_path(
|
||||||
shape_clone,
|
shape_clone,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
trace
|
|
||||||
!("{entity}: remove2");
|
|
||||||
commands
|
commands
|
||||||
.entity(entity)
|
.entity(entity)
|
||||||
.insert(Calculating(task))
|
.insert(Calculating(task))
|
||||||
|
@ -241,45 +221,34 @@ fn calculate_path(
|
||||||
|
|
||||||
fn poll_tasks(
|
fn poll_tasks(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut query: Query<(
|
mut query: Query<(Entity, &mut Calculating, &Transform, &Destination)>,
|
||||||
Entity,
|
|
||||||
&mut Calculating,
|
|
||||||
&Transform,
|
|
||||||
&Destination,
|
|
||||||
Option<&mut ActionState<NegotiatePathAction>>,
|
|
||||||
)>,
|
|
||||||
) {
|
) {
|
||||||
for (entity, mut calculating, transform, destination, actions) in &mut query {
|
for (entity, mut calculating, transform, destination) in &mut query {
|
||||||
if let Some(result) = future::block_on(future::poll_once(&mut **calculating)) {
|
if let Some(result) = future::block_on(future::poll_once(&mut **calculating)) {
|
||||||
if let Some(path) = result {
|
if let Some(path) = result {
|
||||||
trace!("{entity:?}: Path: {path:?}");
|
trace!("{entity:?}: Path: {path:?}");
|
||||||
commands.entity(entity).insert(path);
|
commands.entity(entity).insert(path);
|
||||||
} else {
|
} else {
|
||||||
trace
|
trace!(
|
||||||
!(
|
|
||||||
"{entity:?}: path: no path from {:?} to {:?}",
|
"{entity:?}: path: no path from {:?} to {:?}",
|
||||||
transform.translation.truncate().i32(),
|
transform.translation.truncate().i32(),
|
||||||
**destination
|
**destination
|
||||||
);
|
);
|
||||||
commands.entity(entity).insert(NoPath);
|
commands.entity(entity).insert(NoPath);
|
||||||
if let Some(mut actions) = actions {
|
|
||||||
trace!("{entity:?}: Disabling and resetting because no path");
|
|
||||||
actions.disable();
|
|
||||||
actions.reset_all();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
commands.entity(entity).remove::<Calculating>();
|
commands.entity(entity).remove::<Calculating>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_destination(mut commands: Commands, mut removed: RemovedComponents<Destination>) {
|
fn remove_destination(
|
||||||
|
mut commands: Commands,
|
||||||
|
entities: &Entities,
|
||||||
|
mut removed: RemovedComponents<Destination>,
|
||||||
|
) {
|
||||||
for entity in removed.read() {
|
for entity in removed.read() {
|
||||||
if let Some(mut commands) = commands.get_entity(entity) {
|
if entities.contains(entity) {
|
||||||
commands
|
commands.entity(entity).remove::<Calculating>();
|
||||||
.remove::<Calculating>()
|
|
||||||
.remove::<Path>()
|
|
||||||
.remove::<NoPath>();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -290,7 +259,6 @@ fn negotiate_path(
|
||||||
physics_config: Res<RapierConfiguration>,
|
physics_config: Res<RapierConfiguration>,
|
||||||
mut query: Query<(
|
mut query: Query<(
|
||||||
Entity,
|
Entity,
|
||||||
Option<&mut ActionState<NegotiatePathAction>>,
|
|
||||||
&mut ActionState<NavigationAction>,
|
&mut ActionState<NavigationAction>,
|
||||||
&mut Path,
|
&mut Path,
|
||||||
&mut Transform,
|
&mut Transform,
|
||||||
|
@ -303,18 +271,9 @@ fn negotiate_path(
|
||||||
if !physics_config.physics_pipeline_active || !physics_config.query_pipeline_active {
|
if !physics_config.physics_pipeline_active || !physics_config.query_pipeline_active {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (
|
for (entity, mut actions, mut path, mut transform, collider, speed, rotation_speed) in
|
||||||
entity,
|
&mut query
|
||||||
actions,
|
|
||||||
mut navigation_actions,
|
|
||||||
mut path,
|
|
||||||
mut transform,
|
|
||||||
collider,
|
|
||||||
speed,
|
|
||||||
rotation_speed,
|
|
||||||
) in &mut query
|
|
||||||
{
|
{
|
||||||
trace!("{entity:?}: negotiating path");
|
|
||||||
let start_i32 = transform.translation.truncate().i32();
|
let start_i32 = transform.translation.truncate().i32();
|
||||||
trace!(
|
trace!(
|
||||||
"{entity:?}: start pathfinding from {start_i32:?} to {:?}: at {:?}",
|
"{entity:?}: start pathfinding from {start_i32:?} to {:?}: at {:?}",
|
||||||
|
@ -326,6 +285,7 @@ fn negotiate_path(
|
||||||
path.remove(0);
|
path.remove(0);
|
||||||
}
|
}
|
||||||
if let Some(next) = path.first() {
|
if let Some(next) = path.first() {
|
||||||
|
trace!("{entity:?}: path: moving from {start_i32:?} to {next:?}");
|
||||||
let start = transform.translation.truncate();
|
let start = transform.translation.truncate();
|
||||||
let mut next = Vec2::new(next.0 as f32, next.1 as f32);
|
let mut next = Vec2::new(next.0 as f32, next.1 as f32);
|
||||||
if next.x >= 0. {
|
if next.x >= 0. {
|
||||||
|
@ -362,27 +322,22 @@ fn negotiate_path(
|
||||||
)
|
)
|
||||||
.is_some()
|
.is_some()
|
||||||
{
|
{
|
||||||
trace
|
// trace!("{entity:?} is stuck, hit: {hit:?}, TOI: {toi:?}");
|
||||||
!("{entity:?} is stuck");
|
|
||||||
// TODO: Remove when we have an actual character controller.
|
// TODO: Remove when we have an actual character controller.
|
||||||
next.x = next.x.trunc();
|
|
||||||
next.y = next.y.trunc();
|
|
||||||
transform.translation = next.extend(0.);
|
transform.translation = next.extend(0.);
|
||||||
} else {
|
continue;
|
||||||
navigation_actions.set_axis_pair(&NavigationAction::Translate, direction);
|
|
||||||
}
|
}
|
||||||
|
trace!("{entity:?}: path: direction: {direction:?}");
|
||||||
|
actions.press(&NavigationAction::Translate);
|
||||||
|
actions
|
||||||
|
.action_data_mut_or_default(&NavigationAction::Translate)
|
||||||
|
.axis_pair = Some(DualAxisData::from_xy(direction));
|
||||||
if rotation_speed.is_some() {
|
if rotation_speed.is_some() {
|
||||||
let angle = direction.y.atan2(direction.x);
|
let angle = direction.y.atan2(direction.x);
|
||||||
transform.rotation = Quat::from_rotation_z(angle);
|
transform.rotation = Quat::from_rotation_z(angle);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
trace
|
trace!("{entity:?}: empty path, cleaning");
|
||||||
!("{entity:?}: empty path, cleaning");
|
|
||||||
if let Some(mut actions) = actions {
|
|
||||||
trace!("{entity:?}: Disabling pathfind because at destination");
|
|
||||||
actions.reset_all();
|
|
||||||
actions.disable();
|
|
||||||
}
|
|
||||||
commands
|
commands
|
||||||
.entity(entity)
|
.entity(entity)
|
||||||
.remove::<Path>()
|
.remove::<Path>()
|
||||||
|
@ -397,35 +352,46 @@ fn actions(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut query: Query<(
|
mut query: Query<(
|
||||||
Entity,
|
Entity,
|
||||||
&ActionState<NegotiatePathAction>,
|
&mut ActionState<NegotiatePathAction>,
|
||||||
&mut ActionState<NavigationAction>,
|
&mut ActionState<NavigationAction>,
|
||||||
Option<&mut Destination>,
|
Option<&mut Destination>,
|
||||||
)>,
|
)>,
|
||||||
) {
|
) {
|
||||||
for (entity, actions, mut navigation_action, destination) in &mut query {
|
for (entity, mut actions, mut navigation_action, destination) in &mut query {
|
||||||
if actions.action_disabled(&NegotiatePathAction) {
|
if actions.pressed(&NegotiatePathAction) {
|
||||||
if destination.is_some() {
|
if let Some(pair) = actions.axis_pair(&NegotiatePathAction) {
|
||||||
commands.entity(entity).remove::<Destination>();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let pair = actions.axis_pair(&NegotiatePathAction);
|
|
||||||
trace!("{entity:?}: Negotiating path to {pair:?}");
|
trace!("{entity:?}: Negotiating path to {pair:?}");
|
||||||
let dest = Destination(pair.xy().i32());
|
let dest = Destination(pair.xy().i32());
|
||||||
if let Some(mut current_dest) = destination {
|
if let Some(mut current_dest) = destination {
|
||||||
trace!("Got a destination");
|
trace!("Got a destination");
|
||||||
if *current_dest != dest {
|
if *current_dest != dest {
|
||||||
trace
|
trace!("{entity:?}: New destination {dest:?} differs from {current_dest:?}, zeroing velocity");
|
||||||
!("{entity:?}: New destination {dest:?} differs from {current_dest:?}, zeroing velocity");
|
navigation_action.press(&NavigationAction::SetLinearVelocity);
|
||||||
navigation_action
|
navigation_action
|
||||||
.set_axis_pair(&NavigationAction::SetLinearVelocity, Vec2::ZERO);
|
.action_data_mut_or_default(&NavigationAction::SetLinearVelocity)
|
||||||
|
.axis_pair = Some(DualAxisData::from_xy(Vec2::ZERO));
|
||||||
*current_dest = dest;
|
*current_dest = dest;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
trace
|
trace!("{entity:?}: Adding destination, zeroing velocity");
|
||||||
!("{entity:?}: Adding destination, zeroing velocity");
|
navigation_action.press(&NavigationAction::SetLinearVelocity);
|
||||||
navigation_action.set_axis_pair(&NavigationAction::SetLinearVelocity, Vec2::ZERO);
|
navigation_action
|
||||||
|
.action_data_mut_or_default(&NavigationAction::SetLinearVelocity)
|
||||||
|
.axis_pair = Some(DualAxisData::from_xy(Vec2::ZERO));
|
||||||
commands.entity(entity).insert(dest);
|
commands.entity(entity).insert(dest);
|
||||||
}
|
}
|
||||||
|
} else if destination.is_some() {
|
||||||
|
trace!("No value, resetting");
|
||||||
|
commands
|
||||||
|
.entity(entity)
|
||||||
|
.remove::<Destination>()
|
||||||
|
.remove::<Path>()
|
||||||
|
.remove::<NoPath>();
|
||||||
|
}
|
||||||
|
actions.release(&NegotiatePathAction);
|
||||||
|
actions
|
||||||
|
.action_data_mut_or_default(&NegotiatePathAction)
|
||||||
|
.axis_pair = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -439,13 +405,16 @@ impl Plugin for PathfindingPlugin {
|
||||||
.register_type::<NoPath>()
|
.register_type::<NoPath>()
|
||||||
.register_type::<Path>()
|
.register_type::<Path>()
|
||||||
.register_type::<CostMap>()
|
.register_type::<CostMap>()
|
||||||
.add_systems(PreUpdate, (poll_tasks, negotiate_path).chain())
|
.add_systems(
|
||||||
|
FixedPreUpdate,
|
||||||
|
(poll_tasks, apply_deferred, negotiate_path).chain(),
|
||||||
|
)
|
||||||
.add_systems(
|
.add_systems(
|
||||||
PreUpdate,
|
PreUpdate,
|
||||||
(actions, calculate_path)
|
(actions, apply_deferred, calculate_path)
|
||||||
.chain()
|
.chain()
|
||||||
.after(InputManagerSystem::Tick),
|
.after(InputManagerSystem::Tick),
|
||||||
)
|
)
|
||||||
.add_systems(PostUpdate, remove_destination);
|
.add_systems(FixedPostUpdate, remove_destination);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,31 +146,8 @@ impl Viewshed {
|
||||||
};
|
};
|
||||||
if let Some((opacity, coord_entities)) = result {
|
if let Some((opacity, coord_entities)) = result {
|
||||||
for e in &coord_entities {
|
for e in &coord_entities {
|
||||||
let mut should_insert = true;
|
|
||||||
if coord_entities.len() > 1 {
|
|
||||||
let start = start.translation().truncate();
|
|
||||||
let dest = Vec2::new(coord.x as f32, coord.y as f32);
|
|
||||||
let dir = dest - start;
|
|
||||||
rapier_context.intersections_with_ray(
|
|
||||||
start,
|
|
||||||
dir,
|
|
||||||
1.,
|
|
||||||
true,
|
|
||||||
QueryFilter::new()
|
|
||||||
.exclude_sensors()
|
|
||||||
.exclude_collider(*viewer_entity)
|
|
||||||
.exclude_collider(*e)
|
|
||||||
.predicate(&|e| visible_query.contains(e)),
|
|
||||||
|_, _| {
|
|
||||||
should_insert = false;
|
|
||||||
false
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if should_insert {
|
|
||||||
new_visible_entities.insert(*e);
|
new_visible_entities.insert(*e);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
opacity
|
opacity
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
|
@ -210,7 +187,7 @@ impl Viewshed {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Component, Clone, Copy, Debug, Deref, DerefMut, Eq, PartialEq, Reflect)]
|
#[derive(Component, Clone, Copy, Debug, Deref, DerefMut, Reflect)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct Visible(pub u8);
|
pub struct Visible(pub u8);
|
||||||
|
|
||||||
|
@ -460,9 +437,6 @@ impl<MapData: 'static + Clone + Default + Send + Sync> Plugin for VisibilityPlug
|
||||||
update_revealed_tiles::<MapData>,
|
update_revealed_tiles::<MapData>,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.add_systems(
|
.add_systems(FixedPostUpdate, (log_visible, viewshed_removed, remove_visible));
|
||||||
FixedPostUpdate,
|
|
||||||
(log_visible, viewshed_removed, remove_visible),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user