Skip to content

Commit

Permalink
Make it possible to keep a path target permanent
Browse files Browse the repository at this point in the history
This will make it possible to set a destination and the entity will get
as close as possible after any change to map reach-ability.

Relates to #24.
  • Loading branch information
Indy2222 committed Jul 4, 2022
1 parent c84dd45 commit 9ba988b
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 84 deletions.
2 changes: 1 addition & 1 deletion crates/controller/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ fn right_click_handler(
for entity in selected.iter() {
path_events.send(UpdateEntityPath::new(
entity,
PathTarget::new(target, PathQueryProps::exact()),
PathTarget::new(target, PathQueryProps::exact(), false),
));
}
}
Expand Down
9 changes: 4 additions & 5 deletions crates/movement/src/systems.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::f32::consts::{FRAC_2_PI, PI};

use bevy::prelude::*;
use de_core::{projection::ToMsl, state::GameState};
use de_pathing::PathResult;
use de_pathing::Path;
use iyes_loopless::prelude::*;

const TARGET_ACCURACY: f32 = 0.1;
Expand All @@ -19,20 +19,19 @@ impl Plugin for MovementPlugin {

fn update(
mut commands: Commands,
mut objects: Query<(Entity, &mut PathResult, &mut Transform)>,
mut objects: Query<(Entity, &mut Path, &mut Transform)>,
time: Res<Time>,
) {
let time_delta = time.delta().as_secs_f32();

for (entity, mut path_result, mut transform) in objects.iter_mut() {
let path = path_result.path_mut();
for (entity, mut path, mut transform) in objects.iter_mut() {
let object_to_target = loop {
let target_3d = path.waypoints().last().unwrap().to_msl();
let object_to_target = target_3d - transform.translation;

if object_to_target.length() < TARGET_ACCURACY {
if path.advance() {
commands.entity(entity).remove::<PathResult>();
commands.entity(entity).remove::<Path>();
break object_to_target;
}
} else {
Expand Down
5 changes: 4 additions & 1 deletion crates/pathing/benches/pathing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,10 @@ fn find_path_benchmark(c: &mut Criterion) {
index = (index + 1) % points.len();
let target = points[index];
index = (index + 1) % points.len();
finder.find_path(start, PathTarget::new(target, PathQueryProps::new(0., 10.)));
finder.find_path(
start,
PathTarget::new(target, PathQueryProps::new(0., 10.), false),
);
});
});
}
Expand Down
64 changes: 33 additions & 31 deletions crates/pathing/src/finder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::{
dijkstra::{find_path, PointContext},
exclusion::ExclusionArea,
graph::VisibilityGraph,
path::{Path, PathResult},
path::Path,
utils::HashableSegment,
PathTarget,
};
Expand Down Expand Up @@ -134,11 +134,7 @@ impl PathFinder {
/// Returns a shortest path between two points.
///
/// Returns `None` if there is no path between the two points.
pub fn find_path<P: Into<Point<f32>>>(
&self,
from: P,
target: PathTarget,
) -> Option<PathResult> {
pub fn find_path<P: Into<Point<f32>>>(&self, from: P, target: PathTarget) -> Option<Path> {
let from: Point<f32> = from.into();
let to: Point<f32> = target.location().into();

Expand Down Expand Up @@ -169,16 +165,13 @@ impl PathFinder {
.count()
>= 2
{
debug!(
"Trivial path from {:?} to {:?} found, trimming...",
from, to
);
// Trivial case, both points are in the same triangle.
match Path::straight(from.into(), target.location())
.truncated(target.properties().distance())
{
Some(path) => {
debug!("Trivial path from {:?} to {:?} found", from, to);
return Some(PathResult::new(path, target));
}
None => return None,
}
return Path::straight(from.into(), target.location())
.truncated(target.properties().distance());
}

let source = PointContext::new(from, source_edges);
Expand All @@ -191,7 +184,7 @@ impl PathFinder {
from,
to
);
Some(PathResult::new(path, target))
Some(path)
}
None => {
debug!("No path from {:?} to {:?} found", from, to);
Expand Down Expand Up @@ -357,29 +350,29 @@ mod tests {
];
let finder = PathFinder::from_triangles(triangles, vec![]);

let mut first_path = finder
let first_path = finder
.find_path(
Vec2::new(-460., -950.),
PathTarget::new(Vec2::new(450., 950.), PathQueryProps::exact()),
PathTarget::new(Vec2::new(450., 950.), PathQueryProps::exact(), false),
)
.unwrap();
assert_eq!(
first_path.path_mut().waypoints(),
first_path.waypoints(),
&[
Vec2::new(450., 950.),
Vec2::new(-18.6, 18.6),
Vec2::new(-460., -950.),
]
);

let mut second_path = finder
let second_path = finder
.find_path(
Vec2::new(0.2, -950.),
PathTarget::new(Vec2::new(0., 950.), PathQueryProps::exact()),
PathTarget::new(Vec2::new(0., 950.), PathQueryProps::exact(), false),
)
.unwrap();
assert_eq!(
second_path.path_mut().waypoints(),
second_path.waypoints(),
&[
Vec2::new(0., 950.),
Vec2::new(18.6, 18.6),
Expand All @@ -388,14 +381,18 @@ mod tests {
]
);

let mut third_path = finder
let third_path = finder
.find_path(
Vec2::new(0.2, -950.),
PathTarget::new(Vec2::new(0., 950.), PathQueryProps::new(30., f32::INFINITY)),
PathTarget::new(
Vec2::new(0., 950.),
PathQueryProps::new(30., f32::INFINITY),
false,
),
)
.unwrap();
assert_eq!(
third_path.path_mut().waypoints(),
third_path.waypoints(),
&[
Vec2::new(0.59897804, 920.006),
Vec2::new(18.6, 18.6),
Expand All @@ -404,28 +401,33 @@ mod tests {
]
);

let mut forth_path = finder
let forth_path = finder
.find_path(
Vec2::new(0.2, -950.),
PathTarget::new(
Vec2::new(0., 950.),
PathQueryProps::new(999., f32::INFINITY),
false,
),
)
.unwrap();
assert_eq!(
forth_path.path_mut().waypoints(),
forth_path.waypoints(),
&[Vec2::new(18.003086, -48.81555), Vec2::new(0.2, -950.),]
);

let mut fifth_path = finder
let fifth_path = finder
.find_path(
Vec2::new(0.2, -950.),
PathTarget::new(Vec2::new(1., 8.), PathQueryProps::new(0., f32::INFINITY)),
PathTarget::new(
Vec2::new(1., 8.),
PathQueryProps::new(0., f32::INFINITY),
false,
),
)
.unwrap();
assert_eq!(
fifth_path.path_mut().waypoints(),
fifth_path.waypoints(),
&[
Vec2::new(1.0000019, 18.6),
Vec2::new(18.6, 18.6),
Expand Down Expand Up @@ -462,7 +464,7 @@ mod tests {
assert!(finder
.find_path(
Point::new(-0.5, 0.),
PathTarget::new(Vec2::new(2., 22.), PathQueryProps::exact())
PathTarget::new(Vec2::new(2., 22.), PathQueryProps::exact(), false)
)
.is_none())
}
Expand Down
2 changes: 1 addition & 1 deletion crates/pathing/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ mod triangulation;
mod utils;

use bevy::{app::PluginGroupBuilder, prelude::PluginGroup};
pub use path::{Path, PathResult};
pub use path::Path;
pub use query::{PathQueryProps, PathTarget};
use systems::PathingPlugin;
pub use systems::{create_finder, EntityPathSchedule, UpdateEntityPath};
Expand Down
23 changes: 1 addition & 22 deletions crates/pathing/src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,9 @@ use approx::assert_abs_diff_eq;
use bevy::prelude::Component;
use glam::Vec2;

use crate::PathTarget;

#[derive(Component)]
pub struct PathResult {
path: Path,
target: PathTarget,
}

impl PathResult {
pub(crate) fn new(path: Path, target: PathTarget) -> Self {
Self { path, target }
}

pub fn path_mut(&mut self) -> &mut Path {
&mut self.path
}

pub fn target(&self) -> PathTarget {
self.target
}
}

/// A path on the map defined by a sequence of way points. Start and target
/// position are included.
#[derive(Component)]
pub struct Path {
length: f32,
waypoints: Vec<Vec2>,
Expand Down
14 changes: 12 additions & 2 deletions crates/pathing/src/query.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use bevy::prelude::Component;
use glam::Vec2;

#[derive(Clone, Copy)]
#[derive(Clone, Copy, Component)]
pub struct PathTarget {
location: Vec2,
properties: PathQueryProps,
permanent: bool,
}

impl PathTarget {
Expand All @@ -14,10 +16,14 @@ impl PathTarget {
/// * `location` - desired target location of the path.
///
/// * `properties` - configuration of the path search.
pub fn new(location: Vec2, properties: PathQueryProps) -> Self {
///
/// * `permanent` - whether the entity should try to reach the target
/// indefinitely.
pub fn new(location: Vec2, properties: PathQueryProps, permanent: bool) -> Self {
Self {
location,
properties,
permanent,
}
}

Expand All @@ -28,6 +34,10 @@ impl PathTarget {
pub fn properties(&self) -> PathQueryProps {
self.properties
}

pub fn permanent(&self) -> bool {
self.permanent
}
}

#[derive(Clone, Copy)]
Expand Down
Loading

0 comments on commit 9ba988b

Please sign in to comment.