Add ability to store path cost modifiers as a component.
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
parent
c980854663
commit
0f78ed421d
|
@ -39,10 +39,38 @@ pub struct NoPath;
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct Path(pub Vec<(i32, i32)>);
|
pub struct Path(pub Vec<(i32, i32)>);
|
||||||
|
|
||||||
|
#[derive(Component, Clone, Debug, Default, Reflect)]
|
||||||
|
#[reflect(Component)]
|
||||||
|
pub struct CostMap {
|
||||||
|
width: usize,
|
||||||
|
costs: Vec<f32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CostMap {
|
||||||
|
pub fn new(width: usize, height: usize) -> Self {
|
||||||
|
let count = width * height;
|
||||||
|
Self {
|
||||||
|
width,
|
||||||
|
costs: vec![1.; count],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn modifier(&self, x: usize, y: usize) -> Option<&f32> {
|
||||||
|
let idx = (y as usize) * self.width + (x as usize);
|
||||||
|
self.costs.get(idx)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_modifier(&mut self, x: usize, y: usize, cost: f32) {
|
||||||
|
let idx = (y as usize) * self.width + (x as usize);
|
||||||
|
self.costs[idx] = cost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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,
|
||||||
map: &Map<D>,
|
map: &Map<D>,
|
||||||
|
cost_map: &Option<CostMap>,
|
||||||
) -> Option<(Vec<(i32, i32)>, u32)> {
|
) -> Option<(Vec<(i32, i32)>, u32)> {
|
||||||
astar(
|
astar(
|
||||||
&start.into(),
|
&start.into(),
|
||||||
|
@ -51,7 +79,13 @@ pub fn find_path<D: 'static + Clone + Default + Send + Sync>(
|
||||||
if let Some(tile) = map.at(p.0 as usize, p.1 as usize) {
|
if let Some(tile) = map.at(p.0 as usize, p.1 as usize) {
|
||||||
if tile.is_walkable() {
|
if tile.is_walkable() {
|
||||||
for tile in map.get_available_exits(p.0 as usize, p.1 as usize) {
|
for tile in map.get_available_exits(p.0 as usize, p.1 as usize) {
|
||||||
successors.push(((tile.0 as i32, tile.1 as i32), (tile.2 * 100.) as u32));
|
let mut cost = tile.2 * 100.;
|
||||||
|
if let Some(cost_map) = cost_map {
|
||||||
|
if let Some(modifier) = cost_map.modifier(tile.0, tile.1) {
|
||||||
|
cost *= modifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
successors.push(((tile.0 as i32, tile.1 as i32), cost as u32));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -67,6 +101,7 @@ fn find_path_for_shape<D: 'static + Clone + Default + Send + Sync>(
|
||||||
start: Transform,
|
start: Transform,
|
||||||
destination: Destination,
|
destination: Destination,
|
||||||
map: Map<D>,
|
map: Map<D>,
|
||||||
|
cost_map: &Option<CostMap>,
|
||||||
query_pipeline: QueryPipeline,
|
query_pipeline: QueryPipeline,
|
||||||
collider_set: ColliderSet,
|
collider_set: ColliderSet,
|
||||||
rigid_body_set: RigidBodySet,
|
rigid_body_set: RigidBodySet,
|
||||||
|
@ -97,8 +132,14 @@ fn find_path_for_shape<D: 'static + Clone + Default + Send + Sync>(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
if should_push {
|
if should_push {
|
||||||
|
let mut cost = tile.2 * 100.;
|
||||||
|
if let Some(cost_map) = cost_map {
|
||||||
|
if let Some(modifier) = cost_map.modifier(tile.0, tile.1) {
|
||||||
|
cost *= modifier;
|
||||||
|
}
|
||||||
|
}
|
||||||
successors
|
successors
|
||||||
.push(((tile.0 as i32, tile.1 as i32), (tile.2 * 100.) as u32));
|
.push(((tile.0 as i32, tile.1 as i32), cost as u32));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,12 +167,13 @@ fn calculate_path<D: 'static + Clone + Default + Send + Sync>(
|
||||||
&Destination,
|
&Destination,
|
||||||
&Transform,
|
&Transform,
|
||||||
&Collider,
|
&Collider,
|
||||||
|
Option<&CostMap>,
|
||||||
),
|
),
|
||||||
Changed<Destination>,
|
Changed<Destination>,
|
||||||
>,
|
>,
|
||||||
map: Query<&Map<D>>,
|
map: Query<&Map<D>>,
|
||||||
) {
|
) {
|
||||||
for (entity, handle, destination, coordinates, shape) in query.iter() {
|
for (entity, handle, destination, coordinates, shape, cost_map) in &query {
|
||||||
if coordinates.i32() == **destination {
|
if coordinates.i32() == **destination {
|
||||||
commands
|
commands
|
||||||
.entity(entity)
|
.entity(entity)
|
||||||
|
@ -147,6 +189,7 @@ fn calculate_path<D: 'static + Clone + Default + Send + Sync>(
|
||||||
let destination_clone = *destination;
|
let destination_clone = *destination;
|
||||||
let query_pipeline = rapier_context.query_pipeline.clone();
|
let query_pipeline = rapier_context.query_pipeline.clone();
|
||||||
let map_clone = map.clone();
|
let map_clone = map.clone();
|
||||||
|
let cost_map_clone = cost_map.cloned();
|
||||||
let handle_clone = *handle;
|
let handle_clone = *handle;
|
||||||
let mut collider_set = rapier_context.colliders.clone();
|
let mut collider_set = rapier_context.colliders.clone();
|
||||||
let mut to_remove = vec![];
|
let mut to_remove = vec![];
|
||||||
|
@ -170,6 +213,7 @@ fn calculate_path<D: 'static + Clone + Default + Send + Sync>(
|
||||||
coordinates_clone,
|
coordinates_clone,
|
||||||
destination_clone,
|
destination_clone,
|
||||||
map_clone,
|
map_clone,
|
||||||
|
&cost_map_clone,
|
||||||
query_pipeline,
|
query_pipeline,
|
||||||
collider_set,
|
collider_set,
|
||||||
bodies,
|
bodies,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user