Cache collision data when calculating visibility.

This commit is contained in:
Nolan Darilek 2022-03-17 12:15:30 -05:00
parent 92b0a92a70
commit 0751cf344d

View File

@ -4,7 +4,10 @@ use std::{
marker::PhantomData,
};
use bevy::{core::FixedTimestep, prelude::*};
use bevy::{
core::{FixedTimestep, FloatOrd},
prelude::*,
};
use bevy_rapier2d::{na, na::UnitComplex};
use coord_2d::{Coord, Size};
use derive_more::{Deref, DerefMut};
@ -59,6 +62,7 @@ impl Viewshed {
map: &Map<D>,
visible_query: &Query<&Visible>,
events: &mut EventWriter<VisibilityChanged>,
cache: &mut HashMap<(FloatOrd, FloatOrd), (u8, HashSet<Entity>)>,
) {
let mut context: Context<u8> = Context::default();
let vision_distance = vision_distance::Circle::new(self.range);
@ -70,11 +74,22 @@ impl Viewshed {
let visibility_grid = VisibilityGrid(
map,
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);
if tile.blocks_visibility() {
cache.insert(
(FloatOrd(dest.x), FloatOrd(dest.y)),
(u8::MAX, HashSet::new()),
);
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 {
return u8::MAX;
}
@ -95,6 +110,10 @@ impl Viewshed {
if let Ok(visible) = visible_query.get(entity) {
opacity = **visible;
}
cache.insert(
(FloatOrd(dest.x), FloatOrd(dest.y)),
(opacity, entities.clone()),
);
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() {
if let Ok((viewer_entity, mut viewshed, mut visible_entities, viewer_coordinates)) =
viewers.get_mut(*entity)
@ -311,6 +331,7 @@ fn update_viewshed<D: 'static + Clone + Default + Send + Sync>(
map,
&visible,
&mut changed,
&mut cache,
);
}
}
@ -327,6 +348,7 @@ fn remove_visible<D: 'static + Clone + Default + Send + Sync>(
mut changed: EventWriter<VisibilityChanged>,
) {
for removed in removed.iter() {
let mut cache = HashMap::new();
for (viewer_entity, mut viewshed, mut visible_entities, start) in viewers.iter_mut() {
if !visible_entities.contains(&removed) {
continue;
@ -342,6 +364,7 @@ fn remove_visible<D: 'static + Clone + Default + Send + Sync>(
map,
&visible,
&mut changed,
&mut cache,
);
}
}