Compare commits

...

2 Commits

View File

@ -4,7 +4,10 @@ use std::{
marker::PhantomData, marker::PhantomData,
}; };
use bevy::{core::FixedTimestep, prelude::*}; use bevy::{
core::{FixedTimestep, FloatOrd},
prelude::*,
};
use bevy_rapier2d::{na, na::UnitComplex}; use bevy_rapier2d::{na, na::UnitComplex};
use coord_2d::{Coord, Size}; use coord_2d::{Coord, Size};
use derive_more::{Deref, DerefMut}; use derive_more::{Deref, DerefMut};
@ -59,6 +62,7 @@ impl Viewshed {
map: &Map<D>, map: &Map<D>,
visible_query: &Query<&Visible>, visible_query: &Query<&Visible>,
events: &mut EventWriter<VisibilityChanged>, events: &mut EventWriter<VisibilityChanged>,
cache: &mut HashMap<(FloatOrd, FloatOrd), (u8, HashSet<Entity>)>,
) { ) {
let mut context: Context<u8> = Context::default(); let mut context: Context<u8> = Context::default();
let vision_distance = vision_distance::Circle::new(self.range); let vision_distance = vision_distance::Circle::new(self.range);
@ -70,11 +74,22 @@ impl Viewshed {
let visibility_grid = VisibilityGrid( let visibility_grid = VisibilityGrid(
map, map,
RefCell::new(Box::new(|coord: Coord| { RefCell::new(Box::new(|coord: Coord| {
let dest = point!(coord.x as f32 + 0.5, coord.y as f32 + 0.5);
if let Some((opacity, entities)) = cache.get(&(FloatOrd(dest.x), FloatOrd(dest.y)))
{
for e in entities {
new_visible_entities.insert(*e);
return *opacity;
}
}
let tile = map.at(coord.x as usize, coord.y as usize); let tile = map.at(coord.x as usize, coord.y as usize);
if tile.blocks_visibility() { if tile.blocks_visibility() {
cache.insert(
(FloatOrd(dest.x), FloatOrd(dest.y)),
(u8::MAX, HashSet::new()),
);
return u8::MAX; return u8::MAX;
} }
let dest = point!(coord.x as f32 + 0.5, coord.y as f32 + 0.5);
if na::distance(&origin, &dest) > self.range as f32 { if na::distance(&origin, &dest) > self.range as f32 {
return u8::MAX; return u8::MAX;
} }
@ -95,6 +110,10 @@ impl Viewshed {
if let Ok(visible) = visible_query.get(entity) { if let Ok(visible) = visible_query.get(entity) {
opacity = **visible; opacity = **visible;
} }
cache.insert(
(FloatOrd(dest.x), FloatOrd(dest.y)),
(opacity, entities.clone()),
);
true true
}, },
); );
@ -297,6 +316,7 @@ fn update_viewshed<D: 'static + Clone + Default + Send + Sync>(
} }
} }
} }
let mut cache = HashMap::new();
for entity in to_update.iter() { for entity in to_update.iter() {
if let Ok((viewer_entity, mut viewshed, mut visible_entities, viewer_coordinates)) = if let Ok((viewer_entity, mut viewshed, mut visible_entities, viewer_coordinates)) =
viewers.get_mut(*entity) viewers.get_mut(*entity)
@ -311,6 +331,7 @@ fn update_viewshed<D: 'static + Clone + Default + Send + Sync>(
map, map,
&visible, &visible,
&mut changed, &mut changed,
&mut cache,
); );
} }
} }
@ -327,6 +348,7 @@ fn remove_visible<D: 'static + Clone + Default + Send + Sync>(
mut changed: EventWriter<VisibilityChanged>, mut changed: EventWriter<VisibilityChanged>,
) { ) {
for removed in removed.iter() { for removed in removed.iter() {
let mut cache = HashMap::new();
for (viewer_entity, mut viewshed, mut visible_entities, start) in viewers.iter_mut() { for (viewer_entity, mut viewshed, mut visible_entities, start) in viewers.iter_mut() {
if !visible_entities.contains(&removed) { if !visible_entities.contains(&removed) {
continue; continue;
@ -342,6 +364,7 @@ fn remove_visible<D: 'static + Clone + Default + Send + Sync>(
map, map,
&visible, &visible,
&mut changed, &mut changed,
&mut cache,
); );
} }
} }
@ -431,7 +454,12 @@ impl<D: 'static + Clone + Default + Send + Sync> Plugin for VisibilityPlugin<D>
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_event::<VisibilityChanged>() app.add_event::<VisibilityChanged>()
.add_system(add_visibility_indices::<D>) .add_system(add_visibility_indices::<D>)
.add_system_to_stage(CoreStage::PostUpdate, update_viewshed::<D>) .add_system_set_to_stage(
CoreStage::PostUpdate,
SystemSet::new()
.with_run_criteria(FixedTimestep::step(0.05))
.with_system(update_viewshed::<D>),
)
.add_system_to_stage(CoreStage::PostUpdate, viewshed_removed) .add_system_to_stage(CoreStage::PostUpdate, viewshed_removed)
.add_system_to_stage(CoreStage::PostUpdate, remove_visible::<D>) .add_system_to_stage(CoreStage::PostUpdate, remove_visible::<D>)
.add_system_to_stage(CoreStage::PostUpdate, update_revealed_tiles::<D>) .add_system_to_stage(CoreStage::PostUpdate, update_revealed_tiles::<D>)