diff --git a/src/visibility.rs b/src/visibility.rs index 440e820..214d984 100644 --- a/src/visibility.rs +++ b/src/visibility.rs @@ -159,41 +159,55 @@ fn update_viewshed( collider_query: &QueryPipelineColliderComponentsQuery, map: &Map, visible_query: &Query<&Visible>, + cache: &mut HashMap<(i32, i32), (HashSet, u8)>, events: &mut EventWriter, ) { let mut context: Context = Context::default(); let vision_distance = vision_distance::Circle::new(viewshed.range); + let shape = ColliderShape::cuboid(0.49, 0.49); + let origin = point!(start.x(), start.y()); let coord = Coord::new(start.x_i32(), start.y_i32()); let collider_set = QueryPipelineColliderComponentsSet(&collider_query); - let origin = point!(start.x(), start.y()); let mut new_visible_entities = HashSet::::new(); let visibility_grid = VisibilityGrid( map, RefCell::new(Box::new(|coord: Coord| { + if let Some((entities, opacity)) = cache.get(&(coord.x, coord.y)) { + for e in entities { + new_visible_entities.insert(*e); + } + return *opacity; + } + let tile = map.at(coord.x as usize, coord.y as usize); + if tile.blocks_visibility() { + return u8::MAX; + } + let mut entities = HashSet::new(); + let shape_pos = (Vec2::new(coord.x as f32 + 0.5, coord.y as f32 + 0.5), 0.); let dest = point!(coord.x as f32 + 0.5, coord.y as f32 + 0.5); if na::distance(&origin, &dest) >= viewshed.range as f32 { return u8::MAX; } - let direction = (dest - origin).normalize(); - let ray = Ray::new(origin, direction); - let max_toi = na::distance(&origin, &dest); let mut opacity = 0; - query_pipeline.intersections_with_ray( + query_pipeline.intersections_with_shape( &collider_set, - &ray, - max_toi, - true, + &shape_pos.into(), + &*shape, InteractionGroups::all(), Some(&|v| v.entity() != *viewer_entity && visible_query.get(v.entity()).is_ok()), - |handle, _intersection| { + |handle| { let entity = handle.entity(); - new_visible_entities.insert(entity); + entities.insert(entity); if let Ok(visible) = visible_query.get(entity) { opacity = **visible; } - opacity != u8::MAX + true }, ); + for e in &entities { + new_visible_entities.insert(*e); + } + cache.insert((coord.x, coord.y), (entities, opacity)); opacity })), ); @@ -249,6 +263,7 @@ fn update_viewshed_for_coordinates( continue; } if let Ok(map) = map.single() { + let mut cache = HashMap::new(); update_viewshed( &viewer_entity, &mut viewshed, @@ -258,6 +273,7 @@ fn update_viewshed_for_coordinates( &collider_query, map, &visible_query, + &mut cache, &mut changed, ); } @@ -302,6 +318,7 @@ fn update_viewshed_for_start( .insert(LastStart(start.i32())); if should_update { if let Ok(map) = map.single() { + let mut cache = HashMap::new(); update_viewshed( &viewer_entity, &mut viewshed, @@ -311,6 +328,7 @@ fn update_viewshed_for_start( &collider_query, map, &visible, + &mut cache, &mut changed, ); } @@ -334,6 +352,7 @@ fn remove_visible( } visible_entities.remove(&removed); if let Ok(map) = map.single() { + let mut cache = HashMap::new(); update_viewshed( &viewer_entity, &mut viewshed, @@ -343,6 +362,7 @@ fn remove_visible( &collider_query, map, &visible, + &mut cache, &mut changed, ); } @@ -426,10 +446,12 @@ impl Plugin for VisibilityPlugin { .add_system_to_stage(CoreStage::PostUpdate, viewshed_removed.system()) .add_system_set( SystemSet::new() - .with_run_criteria(FixedTimestep::step(0.25)) + .with_run_criteria(FixedTimestep::step(0.2)) .with_system(update_viewshed_for_coordinates.system()) .with_system(update_viewshed_for_start.system()), ) + //.add_system(update_viewshed_for_coordinates.system()) + //.add_system(update_viewshed_for_start.system()) .add_system_to_stage(CoreStage::PostUpdate, remove_visible.system()) .add_system_to_stage(CoreStage::PostUpdate, update_revealed_tiles.system()) .add_system_to_stage(CoreStage::PostUpdate, log_visible.system());