More tweaks to pathfinding and visibility.

This commit is contained in:
Nolan Darilek 2021-06-16 11:28:06 -05:00
parent 2e805b3b8b
commit 98bca77f66
2 changed files with 128 additions and 44 deletions

View File

@ -45,7 +45,7 @@ fn calculate_path(
mut commands: Commands, mut commands: Commands,
pool: Res<AsyncComputeTaskPool>, pool: Res<AsyncComputeTaskPool>,
mut calculating: Local<HashMap<Entity, Receiver<Path>>>, mut calculating: Local<HashMap<Entity, Receiver<Path>>>,
query: Query<(Entity, &Destination, &Coordinates), Changed<Destination>>, query: Query<(Entity, &Destination, &Coordinates), Without<Path>>,
destinations: Query<&Destination>, destinations: Query<&Destination>,
map: Query<&Map>, map: Query<&Map>,
) { ) {
@ -55,6 +55,8 @@ fn calculate_path(
if let Ok(path) = rx.try_recv() { if let Ok(path) = rx.try_recv() {
commands.entity(*entity).insert(path); commands.entity(*entity).insert(path);
calculating.remove(&entity); calculating.remove(&entity);
} else {
commands.entity(*entity).remove::<Destination>();
} }
} else { } else {
calculating.remove(&entity); calculating.remove(&entity);
@ -104,7 +106,13 @@ fn negotiate_path(
if let Some(upcoming) = iter.next() { if let Some(upcoming) = iter.next() {
new_path = vec![start_i32]; new_path = vec![start_i32];
new_path.append(&mut upcoming.to_vec()); new_path.append(&mut upcoming.to_vec());
} else {
commands.entity(entity).remove::<Path>();
velocity.linvel = Vec2::ZERO.into();
} }
} else {
commands.entity(entity).remove::<Path>();
velocity.linvel = Vec2::ZERO.into();
} }
**path = new_path; **path = new_path;
if path.len() >= 2 { if path.len() >= 2 {
@ -113,7 +121,7 @@ fn negotiate_path(
position.position.translation.y, position.position.translation.y,
); );
let next = path[1]; let next = path[1];
let next = Vec2::new(next.0 as f32, next.1 as f32); let next = Vec2::new(next.0 as f32 + 0.5, next.1 as f32 + 0.5);
if rotation_speed.is_some() { if rotation_speed.is_some() {
let v = next - start; let v = next - start;
let angle = v.y.atan2(v.x); let angle = v.y.atan2(v.x);
@ -121,12 +129,12 @@ fn negotiate_path(
} }
let mut direction = next - start; let mut direction = next - start;
direction = direction.normalize(); direction = direction.normalize();
direction *= speed.0; direction *= **speed;
velocity.linvel = direction.into(); velocity.linvel = direction.into();
} else { } else {
commands.entity(entity).remove::<Path>(); commands.entity(entity).remove::<Path>();
commands.entity(entity).remove::<Destination>();
velocity.linvel = Vec2::ZERO.into(); velocity.linvel = Vec2::ZERO.into();
commands.entity(entity).remove::<Destination>();
} }
} }
} }

View File

@ -94,22 +94,22 @@ where
} }
} }
fn update_viewshed<'a>( fn update_viewshed(
mut viewers: Query<(Entity, &mut Viewshed, &Coordinates), Changed<Coordinates>>, viewer_entity: &Entity,
map: Query<&Map>, viewshed: &mut Viewshed,
query_pipeline: Res<QueryPipeline>, start: &dyn PointLike,
collider_query: QueryPipelineColliderComponentsQuery, query_pipeline: &QueryPipeline,
blocks_visibility: Query<&BlocksVisibility>, collider_query: &QueryPipelineColliderComponentsQuery,
map: &Map,
blocks_visibility: &Query<&BlocksVisibility>,
) { ) {
for (viewer_entity, mut viewshed, start) in viewers.iter_mut() {
for map in map.iter() {
let mut context: Context<u8> = Context::default(); let mut context: Context<u8> = Context::default();
let vision_distance = vision_distance::Circle::new(viewshed.range); let vision_distance = vision_distance::Circle::new(viewshed.range);
let coord = Coord::new(start.x_i32(), start.y_i32()); let coord = Coord::new(start.x_i32(), start.y_i32());
viewshed.visible.clear(); viewshed.visible.clear();
let collider_set = QueryPipelineColliderComponentsSet(&collider_query);
let shape = Cuboid::new(Vec2::new(0.49, 0.49).into()); let shape = Cuboid::new(Vec2::new(0.49, 0.49).into());
let range = viewshed.range as f32; let range = viewshed.range as f32;
let collider_set = QueryPipelineColliderComponentsSet(&collider_query);
let visibility_grid = VisibilityGrid(map, |coord: Coord| { let visibility_grid = VisibilityGrid(map, |coord: Coord| {
if coord.distance(start) > range { if coord.distance(start) > range {
return 255; return 255;
@ -121,9 +121,7 @@ fn update_viewshed<'a>(
&shape_pos.into(), &shape_pos.into(),
&shape, &shape,
InteractionGroups::all(), InteractionGroups::all(),
Some(&|v| { Some(&|v| v.entity() != *viewer_entity && blocks_visibility.get(v.entity()).is_ok()),
v.entity() != viewer_entity && blocks_visibility.get(v.entity()).is_ok()
}),
|_| { |_| {
opacity = 255; opacity = 255;
false false
@ -142,6 +140,79 @@ fn update_viewshed<'a>(
}, },
); );
} }
fn update_viewshed_for_coordinates<'a>(
visible: Query<(&Coordinates, &BlocksVisibility), Changed<Coordinates>>,
mut viewers: Query<(Entity, &mut Viewshed, &Coordinates)>,
map: Query<&Map>,
query_pipeline: Res<QueryPipeline>,
collider_query: QueryPipelineColliderComponentsQuery,
blocks_visibility: Query<&BlocksVisibility>,
) {
for (coordinates, _) in visible.iter() {
for (viewer_entity, mut viewshed, start) in viewers.iter_mut() {
if coordinates.distance(start) > viewshed.range as f32 {
continue;
}
if let Ok(map) = map.single() {
update_viewshed(
&viewer_entity,
&mut viewshed,
start,
&*query_pipeline,
&collider_query,
map,
&blocks_visibility,
);
}
}
}
}
fn update_viewshed_for_start<'a>(
mut viewers: Query<(Entity, &mut Viewshed, &Coordinates), Changed<Coordinates>>,
map: Query<&Map>,
query_pipeline: Res<QueryPipeline>,
collider_query: QueryPipelineColliderComponentsQuery,
blocks_visibility: Query<&BlocksVisibility>,
) {
for (viewer_entity, mut viewshed, start) in viewers.iter_mut() {
if let Ok(map) = map.single() {
update_viewshed(
&viewer_entity,
&mut viewshed,
start,
&*query_pipeline,
&collider_query,
map,
&blocks_visibility,
);
}
}
}
fn remove_blocks_visibility<'a>(
removed: RemovedComponents<BlocksVisibility>,
mut viewers: Query<(Entity, &mut Viewshed, &Coordinates)>,
map: Query<&Map>,
query_pipeline: Res<QueryPipeline>,
collider_query: QueryPipelineColliderComponentsQuery,
blocks_visibility: Query<&BlocksVisibility>,
) {
for _ in removed.iter() {
for (viewer_entity, mut viewshed, start) in viewers.iter_mut() {
if let Ok(map) = map.single() {
update_viewshed(
&viewer_entity,
&mut viewshed,
start,
&*query_pipeline,
&collider_query,
map,
&blocks_visibility,
);
}
}
} }
} }
@ -241,7 +312,12 @@ pub struct VisibilityPlugin;
impl Plugin for VisibilityPlugin { impl Plugin for VisibilityPlugin {
fn build(&self, app: &mut AppBuilder) { fn build(&self, app: &mut AppBuilder) {
app.add_system(add_visibility_indices.system()) app.add_system(add_visibility_indices.system())
.add_system_to_stage(CoreStage::PostUpdate, update_viewshed.system()) .add_system_to_stage(
CoreStage::PostUpdate,
update_viewshed_for_coordinates.system(),
)
.add_system_to_stage(CoreStage::PostUpdate, update_viewshed_for_start.system())
.add_system_to_stage(CoreStage::PostUpdate, remove_blocks_visibility.system())
.add_system_to_stage( .add_system_to_stage(
CoreStage::PostUpdate, CoreStage::PostUpdate,
update_visible_and_revealed_tiles.system(), update_visible_and_revealed_tiles.system(),