Get pathfinding working.
This commit is contained in:
parent
850c5a5cdd
commit
330d915267
|
@ -136,10 +136,8 @@ fn snap(
|
||||||
snap_timers.insert(entity, SnapTimer::default());
|
snap_timers.insert(entity, SnapTimer::default());
|
||||||
transform.rotate(Quat::from_rotation_z(PI));
|
transform.rotate(Quat::from_rotation_z(PI));
|
||||||
} else if actions.just_pressed(&NavigationAction::SnapCardinal) {
|
} else if actions.just_pressed(&NavigationAction::SnapCardinal) {
|
||||||
println!("Direction: {direction:?}");
|
|
||||||
let yaw: Rot2 = direction.into();
|
let yaw: Rot2 = direction.into();
|
||||||
let yaw = yaw.as_radians();
|
let yaw = yaw.as_radians();
|
||||||
println!("Yaw: {yaw}");
|
|
||||||
let rotation = Quat::from_rotation_z(yaw);
|
let rotation = Quat::from_rotation_z(yaw);
|
||||||
if transform.rotation != rotation {
|
if transform.rotation != rotation {
|
||||||
transform.rotation = rotation;
|
transform.rotation = rotation;
|
||||||
|
@ -215,7 +213,6 @@ fn controls(
|
||||||
let mut speed = **speed;
|
let mut speed = **speed;
|
||||||
speed *= movement_factor;
|
speed *= movement_factor;
|
||||||
let move_velocity = direction * speed;
|
let move_velocity = direction * speed;
|
||||||
// println!("{entity:?}: SetLinearVelocity: {velocity:?}");
|
|
||||||
actions.set_axis_pair(&NavigationAction::SetLinearVelocity, move_velocity);
|
actions.set_axis_pair(&NavigationAction::SetLinearVelocity, move_velocity);
|
||||||
}
|
}
|
||||||
if velocity.0 != actions.axis_pair(&NavigationAction::SetLinearVelocity) {
|
if velocity.0 != actions.axis_pair(&NavigationAction::SetLinearVelocity) {
|
||||||
|
@ -224,18 +221,25 @@ fn controls(
|
||||||
if actions.axis_pair(&NavigationAction::Translate) != Vec2::ZERO {
|
if actions.axis_pair(&NavigationAction::Translate) != Vec2::ZERO {
|
||||||
let pair = actions.axis_pair(&NavigationAction::Translate);
|
let pair = actions.axis_pair(&NavigationAction::Translate);
|
||||||
let dir = Dir2::new_unchecked(pair.normalize());
|
let dir = Dir2::new_unchecked(pair.normalize());
|
||||||
if spatial_query
|
let mut can_translate = true;
|
||||||
.cast_shape(
|
spatial_query.shape_hits_callback(
|
||||||
collider,
|
collider,
|
||||||
transform.translation.truncate(),
|
transform.translation.truncate(),
|
||||||
transform.yaw().as_radians(),
|
transform.yaw().as_radians(),
|
||||||
dir,
|
dir,
|
||||||
1.,
|
pair.length(),
|
||||||
true,
|
true,
|
||||||
SpatialQueryFilter::from_excluded_entities(&sensors),
|
SpatialQueryFilter::from_excluded_entities(&sensors),
|
||||||
)
|
|hit| {
|
||||||
.is_none()
|
if hit.entity != entity {
|
||||||
{
|
can_translate = false;
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if can_translate {
|
||||||
transform.translation += pair.extend(0.);
|
transform.translation += pair.extend(0.);
|
||||||
}
|
}
|
||||||
actions.set_axis_pair(&NavigationAction::Translate, Vec2::ZERO);
|
actions.set_axis_pair(&NavigationAction::Translate, Vec2::ZERO);
|
||||||
|
|
|
@ -4,8 +4,8 @@ use leafwing_input_manager::{plugin::InputManagerSystem, prelude::*};
|
||||||
use pathfinding::prelude::*;
|
use pathfinding::prelude::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
core::{GlobalTransformExt, TransformExt},
|
core::GlobalTransformExt,
|
||||||
map::Map,
|
map::{Map, MapObstruction},
|
||||||
navigation::{NavigationAction, RotationSpeed, Speed},
|
navigation::{NavigationAction, RotationSpeed, Speed},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -65,7 +65,8 @@ pub fn find_path<D: 'static + Clone + Default + Send + Sync>(
|
||||||
cost *= modifier;
|
cost *= modifier;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
successors.push((IVec2::new(tile.0 as i32, tile.1 as i32), cost as u32));
|
successors
|
||||||
|
.push((IVec2::new(tile.0 as i32, tile.1 as i32), cost as u32));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,11 +92,12 @@ fn calculate_path(
|
||||||
),
|
),
|
||||||
Changed<Destination>,
|
Changed<Destination>,
|
||||||
>,
|
>,
|
||||||
|
obstructions: Query<Entity, With<MapObstruction>>,
|
||||||
|
sensors: Query<Entity, With<Sensor>>,
|
||||||
) {
|
) {
|
||||||
for (entity, destination, transform, collider, cost_map, actions) in &mut query {
|
for (entity, destination, transform, collider, cost_map, actions) in &mut query {
|
||||||
trace!("{entity}: destination: {destination:?}");
|
trace!("{entity}: destination: {destination:?}");
|
||||||
if transform.translation().truncate().as_ivec2() == **destination {
|
if transform.translation().truncate().as_ivec2() == **destination {
|
||||||
trace!("{entity}: remove1");
|
|
||||||
commands
|
commands
|
||||||
.entity(entity)
|
.entity(entity)
|
||||||
.remove::<Path>()
|
.remove::<Path>()
|
||||||
|
@ -103,10 +105,6 @@ fn calculate_path(
|
||||||
.remove::<Destination>();
|
.remove::<Destination>();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
trace!(
|
|
||||||
"{entity:?}: Calculating path from {:?} to {destination:?}",
|
|
||||||
transform.translation().truncate().as_ivec2()
|
|
||||||
);
|
|
||||||
commands.entity(entity).remove::<Path>().remove::<NoPath>();
|
commands.entity(entity).remove::<Path>().remove::<NoPath>();
|
||||||
let path = astar(
|
let path = astar(
|
||||||
&transform.translation().truncate().as_ivec2(),
|
&transform.translation().truncate().as_ivec2(),
|
||||||
|
@ -126,16 +124,28 @@ fn calculate_path(
|
||||||
];
|
];
|
||||||
for exit in &exits {
|
for exit in &exits {
|
||||||
let mut should_push = true;
|
let mut should_push = true;
|
||||||
if !spatial_query
|
let mut check = exit.0.as_vec2();
|
||||||
.shape_intersections(
|
if check.x >= 0. {
|
||||||
collider,
|
check.x += 0.5;
|
||||||
transform.translation().truncate(),
|
} else {
|
||||||
transform.yaw().as_radians(),
|
check.x -= 0.5;
|
||||||
SpatialQueryFilter::default(),
|
}
|
||||||
)
|
if check.y >= 0. {
|
||||||
.is_empty()
|
check.y += 0.5;
|
||||||
{
|
} else {
|
||||||
should_push = false;
|
check.y -= 0.5;
|
||||||
|
}
|
||||||
|
let hits = spatial_query.shape_intersections(
|
||||||
|
collider,
|
||||||
|
check,
|
||||||
|
transform.yaw().as_radians(),
|
||||||
|
SpatialQueryFilter::from_excluded_entities(&sensors),
|
||||||
|
);
|
||||||
|
for entity in &hits {
|
||||||
|
if obstructions.contains(*entity) {
|
||||||
|
should_push = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if should_push {
|
if should_push {
|
||||||
let mut cost = exit.1 * 100.;
|
let mut cost = exit.1 * 100.;
|
||||||
|
@ -176,6 +186,7 @@ fn remove_destination(mut commands: Commands, mut removed: RemovedComponents<Des
|
||||||
fn negotiate_path(
|
fn negotiate_path(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
|
physics_time: Res<Time<Physics>>,
|
||||||
spatial_query: SpatialQuery,
|
spatial_query: SpatialQuery,
|
||||||
mut query: Query<(
|
mut query: Query<(
|
||||||
Entity,
|
Entity,
|
||||||
|
@ -183,17 +194,24 @@ fn negotiate_path(
|
||||||
&mut ActionState<NavigationAction>,
|
&mut ActionState<NavigationAction>,
|
||||||
&mut Path,
|
&mut Path,
|
||||||
&mut Transform,
|
&mut Transform,
|
||||||
|
&GlobalTransform,
|
||||||
&Collider,
|
&Collider,
|
||||||
&Speed,
|
&Speed,
|
||||||
Option<&RotationSpeed>,
|
Option<&RotationSpeed>,
|
||||||
)>,
|
)>,
|
||||||
|
obstructions: Query<Entity, With<MapObstruction>>,
|
||||||
|
sensors: Query<Entity, With<Sensor>>,
|
||||||
) {
|
) {
|
||||||
|
if physics_time.is_paused() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (
|
for (
|
||||||
entity,
|
entity,
|
||||||
actions,
|
actions,
|
||||||
mut navigation_actions,
|
mut navigation_actions,
|
||||||
mut path,
|
mut path,
|
||||||
mut transform,
|
mut transform,
|
||||||
|
global_transform,
|
||||||
collider,
|
collider,
|
||||||
speed,
|
speed,
|
||||||
rotation_speed,
|
rotation_speed,
|
||||||
|
@ -201,17 +219,12 @@ fn negotiate_path(
|
||||||
{
|
{
|
||||||
trace!("{entity:?}: negotiating path");
|
trace!("{entity:?}: negotiating path");
|
||||||
let start = transform.translation.truncate().as_ivec2();
|
let start = transform.translation.truncate().as_ivec2();
|
||||||
trace!(
|
|
||||||
"{entity:?}: start pathfinding from {start:?} to {:?}: at {:?}",
|
|
||||||
path.last(),
|
|
||||||
transform.translation.truncate()
|
|
||||||
);
|
|
||||||
if path.len() > 0 && path[0] == start {
|
if path.len() > 0 && path[0] == start {
|
||||||
trace!("At start, removing");
|
trace!("At start, removing");
|
||||||
path.remove(0);
|
path.remove(0);
|
||||||
}
|
}
|
||||||
if let Some(next) = path.first() {
|
if let Some(next) = path.first() {
|
||||||
let start = transform.translation.truncate();
|
let start = global_transform.translation().truncate();
|
||||||
let mut next = next.as_vec2();
|
let mut next = next.as_vec2();
|
||||||
if next.x >= 0. {
|
if next.x >= 0. {
|
||||||
next.x += 0.5;
|
next.x += 0.5;
|
||||||
|
@ -226,30 +239,30 @@ fn negotiate_path(
|
||||||
let mut direction = next - start;
|
let mut direction = next - start;
|
||||||
direction = direction.normalize();
|
direction = direction.normalize();
|
||||||
direction *= **speed;
|
direction *= **speed;
|
||||||
direction *= time.delta_seconds();
|
let mut hits = vec![];
|
||||||
trace!(
|
spatial_query.shape_hits_callback(
|
||||||
"{entity:?}: Direction: {direction:?}, Distance: {}",
|
collider,
|
||||||
(next - start).length()
|
start,
|
||||||
|
global_transform.yaw().as_radians(),
|
||||||
|
Dir2::new_unchecked(direction.normalize()),
|
||||||
|
time.delta_seconds(),
|
||||||
|
true,
|
||||||
|
SpatialQueryFilter::from_excluded_entities(&sensors),
|
||||||
|
|hit| {
|
||||||
|
if obstructions.contains(hit.entity) {
|
||||||
|
hits.push(hit.entity);
|
||||||
|
}
|
||||||
|
true
|
||||||
|
},
|
||||||
);
|
);
|
||||||
if spatial_query
|
if !hits.is_empty() {
|
||||||
.cast_shape(
|
|
||||||
collider,
|
|
||||||
start,
|
|
||||||
transform.yaw().as_radians(),
|
|
||||||
Dir2::new_unchecked(direction.normalize()),
|
|
||||||
direction.length(),
|
|
||||||
true,
|
|
||||||
SpatialQueryFilter::default(),
|
|
||||||
)
|
|
||||||
.is_some()
|
|
||||||
{
|
|
||||||
trace!("{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.x = next.x.trunc();
|
||||||
next.y = next.y.trunc();
|
next.y = next.y.trunc();
|
||||||
transform.translation = next.extend(0.);
|
transform.translation = next.extend(0.);
|
||||||
} else {
|
} else {
|
||||||
navigation_actions.set_axis_pair(&NavigationAction::Translate, direction);
|
let delta = direction * time.delta_seconds();
|
||||||
|
navigation_actions.set_axis_pair(&NavigationAction::Translate, delta);
|
||||||
}
|
}
|
||||||
if rotation_speed.is_some() {
|
if rotation_speed.is_some() {
|
||||||
let angle = direction.y.atan2(direction.x);
|
let angle = direction.y.atan2(direction.x);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user