diff --git a/src/pathfinding.rs b/src/pathfinding.rs index 0f9bf7a..fbfe774 100644 --- a/src/pathfinding.rs +++ b/src/pathfinding.rs @@ -45,7 +45,7 @@ fn calculate_path( mut commands: Commands, pool: Res, mut calculating: Local>>, - query: Query<(Entity, &Destination, &Coordinates), Changed>, + query: Query<(Entity, &Destination, &Coordinates), Without>, destinations: Query<&Destination>, map: Query<&Map>, ) { @@ -55,6 +55,8 @@ fn calculate_path( if let Ok(path) = rx.try_recv() { commands.entity(*entity).insert(path); calculating.remove(&entity); + } else { + commands.entity(*entity).remove::(); } } else { calculating.remove(&entity); @@ -104,7 +106,13 @@ fn negotiate_path( if let Some(upcoming) = iter.next() { new_path = vec![start_i32]; new_path.append(&mut upcoming.to_vec()); + } else { + commands.entity(entity).remove::(); + velocity.linvel = Vec2::ZERO.into(); } + } else { + commands.entity(entity).remove::(); + velocity.linvel = Vec2::ZERO.into(); } **path = new_path; if path.len() >= 2 { @@ -113,7 +121,7 @@ fn negotiate_path( position.position.translation.y, ); 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() { let v = next - start; let angle = v.y.atan2(v.x); @@ -121,12 +129,12 @@ fn negotiate_path( } let mut direction = next - start; direction = direction.normalize(); - direction *= speed.0; + direction *= **speed; velocity.linvel = direction.into(); } else { commands.entity(entity).remove::(); - commands.entity(entity).remove::(); velocity.linvel = Vec2::ZERO.into(); + commands.entity(entity).remove::(); } } } diff --git a/src/visibility.rs b/src/visibility.rs index e1e5926..7b72ecf 100644 --- a/src/visibility.rs +++ b/src/visibility.rs @@ -94,7 +94,82 @@ where } } -fn update_viewshed<'a>( +fn update_viewshed( + viewer_entity: &Entity, + viewshed: &mut Viewshed, + start: &dyn PointLike, + query_pipeline: &QueryPipeline, + collider_query: &QueryPipelineColliderComponentsQuery, + map: &Map, + blocks_visibility: &Query<&BlocksVisibility>, +) { + let mut context: Context = Context::default(); + let vision_distance = vision_distance::Circle::new(viewshed.range); + let coord = Coord::new(start.x_i32(), start.y_i32()); + viewshed.visible.clear(); + let shape = Cuboid::new(Vec2::new(0.49, 0.49).into()); + let range = viewshed.range as f32; + let collider_set = QueryPipelineColliderComponentsSet(&collider_query); + let visibility_grid = VisibilityGrid(map, |coord: Coord| { + if coord.distance(start) > range { + return 255; + } + let shape_pos = (Vec2::new(coord.x as f32 + 0.5, coord.y as f32 + 0.5), 0.); + let mut opacity = 0; + query_pipeline.intersections_with_shape( + &collider_set, + &shape_pos.into(), + &shape, + InteractionGroups::all(), + Some(&|v| v.entity() != *viewer_entity && blocks_visibility.get(v.entity()).is_ok()), + |_| { + opacity = 255; + false + }, + ); + opacity + }); + context.for_each_visible( + coord, + &visibility_grid, + &visibility_grid, + vision_distance, + 255, + |coord, _directions, _visibility| { + viewshed.visible.insert((coord.x, coord.y)); + }, + ); +} + +fn update_viewshed_for_coordinates<'a>( + visible: Query<(&Coordinates, &BlocksVisibility), Changed>, + mut viewers: Query<(Entity, &mut Viewshed, &Coordinates)>, + map: Query<&Map>, + query_pipeline: Res, + 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>, map: Query<&Map>, query_pipeline: Res, @@ -102,49 +177,45 @@ fn update_viewshed<'a>( blocks_visibility: Query<&BlocksVisibility>, ) { for (viewer_entity, mut viewshed, start) in viewers.iter_mut() { - for map in map.iter() { - let mut context: Context = Context::default(); - let vision_distance = vision_distance::Circle::new(viewshed.range); - let coord = Coord::new(start.x_i32(), start.y_i32()); - viewshed.visible.clear(); - let collider_set = QueryPipelineColliderComponentsSet(&collider_query); - let shape = Cuboid::new(Vec2::new(0.49, 0.49).into()); - let range = viewshed.range as f32; - let visibility_grid = VisibilityGrid(map, |coord: Coord| { - if coord.distance(start) > range { - return 255; - } - let shape_pos = (Vec2::new(coord.x as f32 + 0.5, coord.y as f32 + 0.5), 0.); - let mut opacity = 0; - query_pipeline.intersections_with_shape( - &collider_set, - &shape_pos.into(), - &shape, - InteractionGroups::all(), - Some(&|v| { - v.entity() != viewer_entity && blocks_visibility.get(v.entity()).is_ok() - }), - |_| { - opacity = 255; - false - }, - ); - opacity - }); - context.for_each_visible( - coord, - &visibility_grid, - &visibility_grid, - vision_distance, - 255, - |coord, _directions, _visibility| { - viewshed.visible.insert((coord.x, coord.y)); - }, + 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, + mut viewers: Query<(Entity, &mut Viewshed, &Coordinates)>, + map: Query<&Map>, + query_pipeline: Res, + 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, + ); + } + } + } +} + fn update_visible_and_revealed_tiles( mut map: Query<(&Map, &mut RevealedTiles, &mut VisibleTiles)>, viewers: Query<&Viewshed, With>, @@ -241,7 +312,12 @@ pub struct VisibilityPlugin; impl Plugin for VisibilityPlugin { fn build(&self, app: &mut AppBuilder) { 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( CoreStage::PostUpdate, update_visible_and_revealed_tiles.system(),