Refactor visibility to use physics system.
This commit is contained in:
parent
eefd3a2209
commit
173630edab
|
@ -21,7 +21,7 @@ impl Coordinates {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_transform(&self, config: &CoreConfig) -> Transform {
|
pub fn to_transform(&self, config: &CoreConfig) -> Transform {
|
||||||
Transform::from_translation(Vec3::new(
|
Transform::from_translation(Vec3::new(
|
||||||
self.0 .0 * config.pixels_per_unit as f32,
|
self.0 .0 * config.pixels_per_unit as f32,
|
||||||
self.0 .1 * config.pixels_per_unit as f32,
|
self.0 .1 * config.pixels_per_unit as f32,
|
||||||
|
|
|
@ -2,6 +2,7 @@ use std::{error::Error, hash::Hash, marker::PhantomData};
|
||||||
|
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy_input_actionmap::InputMap;
|
use bevy_input_actionmap::InputMap;
|
||||||
|
use bevy_rapier2d::prelude::*;
|
||||||
use bevy_tts::Tts;
|
use bevy_tts::Tts;
|
||||||
use derive_more::{Deref, DerefMut};
|
use derive_more::{Deref, DerefMut};
|
||||||
use mapgen::TileType;
|
use mapgen::TileType;
|
||||||
|
@ -328,13 +329,17 @@ fn exploration_changed_announcement(
|
||||||
names: Query<&Name>,
|
names: Query<&Name>,
|
||||||
types: Query<&ExplorationType>,
|
types: Query<&ExplorationType>,
|
||||||
mappables: Query<&Mappable>,
|
mappables: Query<&Mappable>,
|
||||||
|
query_pipeline: Res<QueryPipeline>,
|
||||||
|
collider_query: QueryPipelineColliderComponentsQuery,
|
||||||
) -> Result<(), Box<dyn Error>> {
|
) -> Result<(), Box<dyn Error>> {
|
||||||
for (coordinates, exploring) in explorers.iter() {
|
for (coordinates, exploring) in explorers.iter() {
|
||||||
|
let collider_set = QueryPipelineColliderComponentsSet(&collider_query);
|
||||||
let coordinates = **coordinates;
|
let coordinates = **coordinates;
|
||||||
let coordinates = (coordinates.0.floor(), coordinates.1.floor());
|
let coordinates = (coordinates.0.floor(), coordinates.1.floor());
|
||||||
for (map, revealed_tiles, visible_tiles) in map.iter() {
|
for (map, revealed_tiles, visible_tiles) in map.iter() {
|
||||||
let point = **exploring;
|
let point = **exploring;
|
||||||
let idx = point.to_index(map.width());
|
let idx = point.to_index(map.width());
|
||||||
|
let shape = Cuboid::new(Vec2::new(0.5, 0.5).into());
|
||||||
let known = revealed_tiles[idx];
|
let known = revealed_tiles[idx];
|
||||||
let visible = visible_tiles[idx];
|
let visible = visible_tiles[idx];
|
||||||
let fog_of_war = known && !visible;
|
let fog_of_war = known && !visible;
|
||||||
|
@ -343,21 +348,31 @@ fn exploration_changed_announcement(
|
||||||
for (entity, _) in focused.iter() {
|
for (entity, _) in focused.iter() {
|
||||||
commands.entity(entity).remove::<ExplorationFocused>();
|
commands.entity(entity).remove::<ExplorationFocused>();
|
||||||
}
|
}
|
||||||
for entity in &map.entities[idx] {
|
let shape_pos = (Vec2::new(exploring.x(), exploring.y()), 0.);
|
||||||
commands
|
query_pipeline.intersections_with_shape(
|
||||||
.entity(*entity)
|
&collider_set,
|
||||||
.insert(ExplorationFocused::default());
|
&shape_pos.into(),
|
||||||
if visible || mappables.get(*entity).is_ok() {
|
&shape,
|
||||||
if let Ok(name) = names.get(*entity) {
|
InteractionGroups::all(),
|
||||||
tokens.push(name.as_str());
|
None,
|
||||||
}
|
|handle| {
|
||||||
if tokens.is_empty() {
|
let entity = handle.entity();
|
||||||
if let Ok(t) = types.get(*entity) {
|
commands
|
||||||
tokens.push((*t).into());
|
.entity(entity)
|
||||||
|
.insert(ExplorationFocused::default());
|
||||||
|
if visible || mappables.get(entity).is_ok() {
|
||||||
|
if let Ok(name) = names.get(entity) {
|
||||||
|
tokens.push(name.as_str());
|
||||||
|
}
|
||||||
|
if tokens.is_empty() {
|
||||||
|
if let Ok(t) = types.get(entity) {
|
||||||
|
tokens.push((*t).into());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
true
|
||||||
}
|
},
|
||||||
|
);
|
||||||
if tokens.is_empty() {
|
if tokens.is_empty() {
|
||||||
match map.base.tiles[idx] {
|
match map.base.tiles[idx] {
|
||||||
TileType::Floor => "Floor".to_string(),
|
TileType::Floor => "Floor".to_string(),
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#![allow(unused_imports)]
|
||||||
#![allow(clippy::too_many_arguments)]
|
#![allow(clippy::too_many_arguments)]
|
||||||
#![allow(clippy::type_complexity)]
|
#![allow(clippy::type_complexity)]
|
||||||
|
|
||||||
|
|
60
src/map.rs
60
src/map.rs
|
@ -29,16 +29,12 @@ pub struct Portal;
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
pub struct Map {
|
pub struct Map {
|
||||||
pub base: MapgenMap,
|
pub base: MapgenMap,
|
||||||
pub entities: Vec<HashSet<Entity>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Map {
|
impl Map {
|
||||||
pub fn new(base: MapgenMap) -> Self {
|
pub fn new(base: MapgenMap) -> Self {
|
||||||
let count = (base.width * base.height) as usize;
|
let count = (base.width * base.height) as usize;
|
||||||
Self {
|
Self { base }
|
||||||
base,
|
|
||||||
entities: vec![HashSet::new(); count],
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn width(&self) -> usize {
|
pub fn width(&self) -> usize {
|
||||||
|
@ -358,38 +354,6 @@ fn area_description(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_coordinates(removed: RemovedComponents<Coordinates>, mut map: Query<&mut Map>) {
|
|
||||||
for removed in removed.iter() {
|
|
||||||
for mut map in map.iter_mut() {
|
|
||||||
for entities in map.entities.iter_mut() {
|
|
||||||
entities.retain(|e| *e != removed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Deref, DerefMut)]
|
|
||||||
struct PreviousIndex(HashMap<Entity, usize>);
|
|
||||||
|
|
||||||
fn entity_indexing(
|
|
||||||
mut map: Query<&mut Map>,
|
|
||||||
mut previous_index: ResMut<PreviousIndex>,
|
|
||||||
query: Query<(Entity, &Coordinates), Changed<Coordinates>>,
|
|
||||||
) {
|
|
||||||
for (entity, coordinates) in query.iter() {
|
|
||||||
for mut map in map.iter_mut() {
|
|
||||||
let idx = coordinates.to_index(map.width());
|
|
||||||
if let Some(prev_idx) = previous_index.get(&entity) {
|
|
||||||
if idx != *prev_idx {
|
|
||||||
map.entities[*prev_idx].retain(|&e| e != entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
map.entities[idx].insert(entity);
|
|
||||||
previous_index.insert(entity, idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_areas(mut commands: Commands, query: Query<(Entity, &Map), (Added<Map>, Without<Areas>)>) {
|
fn add_areas(mut commands: Commands, query: Query<(Entity, &Map), (Added<Map>, Without<Areas>)>) {
|
||||||
for (entity, map) in query.iter() {
|
for (entity, map) in query.iter() {
|
||||||
let mut v = vec![];
|
let mut v = vec![];
|
||||||
|
@ -403,8 +367,6 @@ fn add_areas(mut commands: Commands, query: Query<(Entity, &Map), (Added<Map>, W
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const UPDATE_ENTITY_INDEX_LABEL: &str = "UPDATE_ENTITY_INDEX";
|
|
||||||
|
|
||||||
pub struct MapPlugin;
|
pub struct MapPlugin;
|
||||||
|
|
||||||
impl Plugin for MapPlugin {
|
impl Plugin for MapPlugin {
|
||||||
|
@ -413,27 +375,9 @@ impl Plugin for MapPlugin {
|
||||||
app.insert_resource(MapConfig::default());
|
app.insert_resource(MapConfig::default());
|
||||||
}
|
}
|
||||||
let config = app.world().get_resource::<MapConfig>().unwrap().clone();
|
let config = app.world().get_resource::<MapConfig>().unwrap().clone();
|
||||||
const SPAWN_PORTALS: &str = "SPAWN_PORTALS";
|
|
||||||
app.register_type::<Portal>()
|
app.register_type::<Portal>()
|
||||||
.insert_resource(PreviousIndex::default())
|
|
||||||
.add_system(add_map_colliders.system())
|
.add_system(add_map_colliders.system())
|
||||||
.add_system(entity_indexing.system().label(UPDATE_ENTITY_INDEX_LABEL))
|
.add_system(portal_spawner.system())
|
||||||
.add_system(
|
|
||||||
portal_spawner
|
|
||||||
.system()
|
|
||||||
.label(SPAWN_PORTALS)
|
|
||||||
.before(UPDATE_ENTITY_INDEX_LABEL),
|
|
||||||
)
|
|
||||||
.add_system_to_stage(
|
|
||||||
CoreStage::PostUpdate,
|
|
||||||
remove_coordinates
|
|
||||||
.system()
|
|
||||||
.before(UPDATE_ENTITY_INDEX_LABEL),
|
|
||||||
)
|
|
||||||
.add_system_to_stage(
|
|
||||||
CoreStage::PostUpdate,
|
|
||||||
entity_indexing.system().label(UPDATE_ENTITY_INDEX_LABEL),
|
|
||||||
)
|
|
||||||
.add_system(add_areas.system())
|
.add_system(add_areas.system())
|
||||||
.add_system_to_stage(CoreStage::PostUpdate, add_areas.system());
|
.add_system_to_stage(CoreStage::PostUpdate, add_areas.system());
|
||||||
if config.speak_area_descriptions {
|
if config.speak_area_descriptions {
|
||||||
|
|
|
@ -6,6 +6,7 @@ use derive_more::{Deref, DerefMut};
|
||||||
use shadowcast::{vision_distance, Context, InputGrid};
|
use shadowcast::{vision_distance, Context, InputGrid};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
bevy_rapier2d::prelude::*,
|
||||||
core::{Angle, Coordinates, Player, PointLike},
|
core::{Angle, Coordinates, Player, PointLike},
|
||||||
log::Log,
|
log::Log,
|
||||||
map::{ITileType, Map, MapConfig},
|
map::{ITileType, Map, MapConfig},
|
||||||
|
@ -44,33 +45,16 @@ impl Viewshed {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Deref, DerefMut, Reflect)]
|
|
||||||
#[reflect(Component)]
|
|
||||||
pub struct VisibilityBlocked(pub Vec<bool>);
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Deref, DerefMut, Reflect)]
|
#[derive(Clone, Debug, Default, Deref, DerefMut, Reflect)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct VisibleTiles(pub Vec<bool>);
|
pub struct VisibleTiles(pub Vec<bool>);
|
||||||
|
|
||||||
fn add_visibility_indices(
|
fn add_visibility_indices(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
query: Query<
|
query: Query<(Entity, &Map), (Added<Map>, Without<VisibleTiles>, Without<RevealedTiles>)>,
|
||||||
(Entity, &Map),
|
|
||||||
(
|
|
||||||
Added<Map>,
|
|
||||||
Without<VisibilityBlocked>,
|
|
||||||
Without<VisibleTiles>,
|
|
||||||
Without<RevealedTiles>,
|
|
||||||
),
|
|
||||||
>,
|
|
||||||
map_config: Res<MapConfig>,
|
map_config: Res<MapConfig>,
|
||||||
) {
|
) {
|
||||||
for (entity, map) in query.iter() {
|
for (entity, map) in query.iter() {
|
||||||
let mut v = vec![];
|
|
||||||
for tile in &map.base.tiles {
|
|
||||||
v.push(tile.blocks_visibility());
|
|
||||||
}
|
|
||||||
commands.entity(entity).insert(VisibilityBlocked(v));
|
|
||||||
let count = map.count();
|
let count = map.count();
|
||||||
commands
|
commands
|
||||||
.entity(entity)
|
.entity(entity)
|
||||||
|
@ -81,85 +65,13 @@ fn add_visibility_indices(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn set_visibility_blocked(
|
struct VisibilityGrid<'a, F>(&'a Map, F);
|
||||||
map: &Map,
|
|
||||||
index: usize,
|
|
||||||
visibility_blockers: &Query<&BlocksVisibility>,
|
|
||||||
visibility_blocked: &mut VisibilityBlocked,
|
|
||||||
) {
|
|
||||||
let mut new_visibility_blocked = map.base.tiles[index].blocks_visibility();
|
|
||||||
if !new_visibility_blocked {
|
|
||||||
for e in &map.entities[index] {
|
|
||||||
if visibility_blockers.get(*e).is_ok() {
|
|
||||||
new_visibility_blocked = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
visibility_blocked[index] = new_visibility_blocked;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Deref, DerefMut)]
|
impl<'a, F> InputGrid for VisibilityGrid<'a, F>
|
||||||
struct PrevIndex(HashMap<Entity, usize>);
|
where
|
||||||
|
F: Fn(Coord) -> u8,
|
||||||
fn map_visibility_indexing(
|
{
|
||||||
mut map: Query<(&Map, &mut VisibilityBlocked)>,
|
type Grid = VisibilityGrid<'a, F>;
|
||||||
mut prev_index: ResMut<PrevIndex>,
|
|
||||||
query: Query<
|
|
||||||
(Entity, &Coordinates),
|
|
||||||
(
|
|
||||||
With<BlocksVisibility>,
|
|
||||||
Or<(Changed<Coordinates>, Changed<BlocksVisibility>)>,
|
|
||||||
),
|
|
||||||
>,
|
|
||||||
visibility_blockers: Query<&BlocksVisibility>,
|
|
||||||
) {
|
|
||||||
for (entity, coordinates) in query.iter() {
|
|
||||||
for (map, mut visibility_blocked) in map.iter_mut() {
|
|
||||||
let idx = coordinates.to_index(map.width());
|
|
||||||
if let Some(prev_idx) = prev_index.get(&entity) {
|
|
||||||
if *prev_idx == idx {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
set_visibility_blocked(
|
|
||||||
&map,
|
|
||||||
*prev_idx,
|
|
||||||
&visibility_blockers,
|
|
||||||
&mut visibility_blocked,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
visibility_blocked[idx] = true;
|
|
||||||
prev_index.insert(entity, idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remove_blocks_visibility(
|
|
||||||
mut prev_index: ResMut<PrevIndex>,
|
|
||||||
mut map: Query<(&Map, &mut VisibilityBlocked)>,
|
|
||||||
removed: RemovedComponents<BlocksVisibility>,
|
|
||||||
coordinates: Query<&Coordinates>,
|
|
||||||
blocks_visibility: Query<&BlocksVisibility>,
|
|
||||||
) {
|
|
||||||
for entity in removed.iter() {
|
|
||||||
for (map, mut visibility_blocked) in map.iter_mut() {
|
|
||||||
let prev = prev_index.get(&entity).cloned();
|
|
||||||
if let Some(prev) = prev {
|
|
||||||
prev_index.remove(&entity);
|
|
||||||
set_visibility_blocked(&map, prev, &blocks_visibility, &mut visibility_blocked);
|
|
||||||
}
|
|
||||||
if let Ok(coordinates) = coordinates.get_component::<Coordinates>(entity) {
|
|
||||||
let idx = coordinates.to_index(map.width());
|
|
||||||
set_visibility_blocked(&map, idx, &blocks_visibility, &mut visibility_blocked);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct VisibilityGrid(Map, VisibilityBlocked);
|
|
||||||
|
|
||||||
impl InputGrid for VisibilityGrid {
|
|
||||||
type Grid = VisibilityGrid;
|
|
||||||
|
|
||||||
type Opacity = u8;
|
type Opacity = u8;
|
||||||
|
|
||||||
|
@ -167,115 +79,58 @@ impl InputGrid for VisibilityGrid {
|
||||||
Size::new(grid.0.width() as u32, grid.0.height() as u32)
|
Size::new(grid.0.width() as u32, grid.0.height() as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_opacity(&self, grid: &Self::Grid, coord: Coord) -> Self::Opacity {
|
fn get_opacity(&self, _grid: &Self::Grid, coord: Coord) -> Self::Opacity {
|
||||||
let point = (coord.x, coord.y);
|
self.1(coord)
|
||||||
let index = point.to_index(grid.0.width());
|
|
||||||
if grid.1 .0[index] {
|
|
||||||
255
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_viewshed(
|
fn update_viewshed<'a>(
|
||||||
viewshed: &mut Viewshed,
|
|
||||||
start: &Coordinates,
|
|
||||||
map: &Map,
|
|
||||||
visibility_blocked: &VisibilityBlocked,
|
|
||||||
) {
|
|
||||||
let mut context: Context<u8> = 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 visibility_grid = VisibilityGrid(map.clone(), visibility_blocked.clone());
|
|
||||||
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(
|
|
||||||
mut viewers: Query<(&mut Viewshed, &Coordinates), Changed<Coordinates>>,
|
mut viewers: Query<(&mut Viewshed, &Coordinates), Changed<Coordinates>>,
|
||||||
map: Query<(&Map, &VisibilityBlocked)>,
|
map: Query<&Map>,
|
||||||
|
query_pipeline: Res<QueryPipeline>,
|
||||||
|
collider_query: QueryPipelineColliderComponentsQuery,
|
||||||
|
blocks_visibility: Query<&BlocksVisibility>,
|
||||||
) {
|
) {
|
||||||
for (mut viewshed, start) in viewers.iter_mut() {
|
for (mut viewshed, start) in viewers.iter_mut() {
|
||||||
for (map, visibility_blocked) in map.iter() {
|
for map in map.iter() {
|
||||||
update_viewshed(&mut viewshed, start, &map, &visibility_blocked);
|
let mut context: Context<u8> = 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.5, 0.5).into());
|
||||||
|
let visibility_grid = VisibilityGrid(map, |coord: Coord| {
|
||||||
|
let shape_pos = (Vec2::new(coord.x as f32, coord.y as f32), 0.);
|
||||||
|
let mut opacity = 0;
|
||||||
|
query_pipeline.intersections_with_shape(
|
||||||
|
&collider_set,
|
||||||
|
&shape_pos.into(),
|
||||||
|
&shape,
|
||||||
|
InteractionGroups::all(),
|
||||||
|
Some(&|v| 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));
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Deref, DerefMut)]
|
|
||||||
struct PrevVisibilityBlocked(Vec<bool>);
|
|
||||||
|
|
||||||
fn visibility_blocked_added(
|
|
||||||
mut prev_visibility_blocked: ResMut<PrevVisibilityBlocked>,
|
|
||||||
added: Query<&VisibilityBlocked, Added<VisibilityBlocked>>,
|
|
||||||
) {
|
|
||||||
for visibility_blocked in added.iter() {
|
|
||||||
**prev_visibility_blocked = visibility_blocked.to_vec();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visibility_blocked_removed(
|
|
||||||
mut prev_visibility_blocked: ResMut<PrevVisibilityBlocked>,
|
|
||||||
removed: RemovedComponents<VisibilityBlocked>,
|
|
||||||
) {
|
|
||||||
for _ in removed.iter() {
|
|
||||||
prev_visibility_blocked.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_viewshed_for_visibility_blocked(
|
|
||||||
mut prev_visibility_blocked: ResMut<PrevVisibilityBlocked>,
|
|
||||||
map: Query<(&Map, &VisibilityBlocked), Changed<VisibilityBlocked>>,
|
|
||||||
mut queryset: QuerySet<(
|
|
||||||
Query<(Entity, &Viewshed)>,
|
|
||||||
Query<(&mut Viewshed, &Coordinates)>,
|
|
||||||
)>,
|
|
||||||
) {
|
|
||||||
for (map, visibility_blocked) in map.iter() {
|
|
||||||
let mut to_check = vec![];
|
|
||||||
for (index, new) in visibility_blocked.iter().enumerate() {
|
|
||||||
let changed = if let Some(prev) = prev_visibility_blocked.get(index) {
|
|
||||||
prev != new
|
|
||||||
} else {
|
|
||||||
true
|
|
||||||
};
|
|
||||||
if changed {
|
|
||||||
let coords = (index % map.width(), index / map.width());
|
|
||||||
for (entity, viewshed) in queryset.q0().iter() {
|
|
||||||
if viewshed.is_visible(&coords) {
|
|
||||||
to_check.push(entity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
to_check.dedup();
|
|
||||||
for entity in to_check {
|
|
||||||
if let Ok((mut viewshed, coordinates)) = queryset.q1_mut().get_mut(entity) {
|
|
||||||
update_viewshed(&mut viewshed, coordinates, &map, &visibility_blocked);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
**prev_visibility_blocked = visibility_blocked.to_vec();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_visible_and_revealed_tiles(
|
fn update_visible_and_revealed_tiles(
|
||||||
mut map: Query<
|
mut map: Query<(&Map, &mut RevealedTiles, &mut VisibleTiles)>,
|
||||||
(&Map, &mut RevealedTiles, &mut VisibleTiles),
|
|
||||||
(
|
|
||||||
With<VisibilityBlocked>,
|
|
||||||
Or<(Changed<Map>, Changed<VisibilityBlocked>)>,
|
|
||||||
),
|
|
||||||
>,
|
|
||||||
viewers: Query<&Viewshed, With<Player>>,
|
viewers: Query<&Viewshed, With<Player>>,
|
||||||
) {
|
) {
|
||||||
for (map, mut revealed_tiles, mut visible_tiles) in map.iter_mut() {
|
for (map, mut revealed_tiles, mut visible_tiles) in map.iter_mut() {
|
||||||
|
@ -296,9 +151,10 @@ fn log_visible(
|
||||||
time: Res<Time>,
|
time: Res<Time>,
|
||||||
mut seen: Local<HashSet<Entity>>,
|
mut seen: Local<HashSet<Entity>>,
|
||||||
mut recently_lost: Local<HashMap<Entity, Timer>>,
|
mut recently_lost: Local<HashMap<Entity, Timer>>,
|
||||||
|
query_pipeline: Res<QueryPipeline>,
|
||||||
|
collider_query: QueryPipelineColliderComponentsQuery,
|
||||||
mut log: Query<&mut Log>,
|
mut log: Query<&mut Log>,
|
||||||
viewers: Query<(&Viewshed, &Coordinates, &Transform), With<Player>>,
|
viewers: Query<(&Viewshed, &Coordinates, &Transform), With<Player>>,
|
||||||
map: Query<&Map>,
|
|
||||||
names: Query<&Name>,
|
names: Query<&Name>,
|
||||||
players: Query<&Player>,
|
players: Query<&Player>,
|
||||||
dont_log_when_visible: Query<&DontLogWhenVisible>,
|
dont_log_when_visible: Query<&DontLogWhenVisible>,
|
||||||
|
@ -315,17 +171,29 @@ fn log_visible(
|
||||||
let mut new_seen = HashSet::new();
|
let mut new_seen = HashSet::new();
|
||||||
if let Ok(mut log) = log.single_mut() {
|
if let Ok(mut log) = log.single_mut() {
|
||||||
for (viewshed, coordinates, transform) in viewers.iter() {
|
for (viewshed, coordinates, transform) in viewers.iter() {
|
||||||
|
let collider_set = QueryPipelineColliderComponentsSet(&collider_query);
|
||||||
|
let shape = Cuboid::new(Vec2::new(0.5, 0.5).into());
|
||||||
for viewed_coordinates in &viewshed.visible {
|
for viewed_coordinates in &viewshed.visible {
|
||||||
for map in map.iter() {
|
let shape_pos = (
|
||||||
let index = viewed_coordinates.to_index(map.width());
|
Vec2::new(viewed_coordinates.x() + 0.5, viewed_coordinates.y() + 0.5),
|
||||||
for entity in &map.entities[index] {
|
0.0,
|
||||||
|
)
|
||||||
|
.into();
|
||||||
|
query_pipeline.intersections_with_shape(
|
||||||
|
&collider_set,
|
||||||
|
&shape_pos,
|
||||||
|
&shape,
|
||||||
|
InteractionGroups::all(),
|
||||||
|
None,
|
||||||
|
|handle| {
|
||||||
|
let entity = handle.entity();
|
||||||
if recently_lost.contains_key(&entity) {
|
if recently_lost.contains_key(&entity) {
|
||||||
continue;
|
return true;
|
||||||
}
|
}
|
||||||
if let Ok(name) = names.get(*entity) {
|
if let Ok(name) = names.get(entity) {
|
||||||
if players.get(*entity).is_err() {
|
if players.get(entity).is_err() {
|
||||||
if !seen.contains(&*entity)
|
if !seen.contains(&entity)
|
||||||
&& dont_log_when_visible.get(*entity).is_err()
|
&& dont_log_when_visible.get(entity).is_err()
|
||||||
{
|
{
|
||||||
let name = name.to_string();
|
let name = name.to_string();
|
||||||
let forward = transform.local_x();
|
let forward = transform.local_x();
|
||||||
|
@ -334,11 +202,12 @@ fn log_visible(
|
||||||
.direction_and_distance(viewed_coordinates, Some(yaw));
|
.direction_and_distance(viewed_coordinates, Some(yaw));
|
||||||
log.push(format!("{}: {}", name, location));
|
log.push(format!("{}: {}", name, location));
|
||||||
}
|
}
|
||||||
new_seen.insert(*entity);
|
new_seen.insert(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
true
|
||||||
}
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -355,60 +224,12 @@ pub struct VisibilityPlugin;
|
||||||
|
|
||||||
impl Plugin for VisibilityPlugin {
|
impl Plugin for VisibilityPlugin {
|
||||||
fn build(&self, app: &mut AppBuilder) {
|
fn build(&self, app: &mut AppBuilder) {
|
||||||
const UPDATE_VISIBILITY_INDEX: &str = "UPDATE_VISIBILITY_INDEX";
|
app.add_system(add_visibility_indices.system())
|
||||||
const UPDATE_VIEWSHED: &str = "UPDATE_VIEWSHED";
|
.add_system_to_stage(CoreStage::PostUpdate, update_viewshed.system())
|
||||||
const MAP_VISIBILITY: &str = "MAP_VISIBILITY";
|
|
||||||
app.init_resource::<PrevVisibilityBlocked>()
|
|
||||||
.init_resource::<PrevIndex>()
|
|
||||||
.add_system(visibility_blocked_added.system())
|
|
||||||
.add_system_to_stage(CoreStage::PostUpdate, visibility_blocked_removed.system())
|
|
||||||
.add_system(add_visibility_indices.system())
|
|
||||||
.add_system_to_stage(
|
.add_system_to_stage(
|
||||||
CoreStage::PostUpdate,
|
CoreStage::PostUpdate,
|
||||||
add_visibility_indices
|
update_visible_and_revealed_tiles.system(),
|
||||||
.system()
|
|
||||||
.before(UPDATE_VISIBILITY_INDEX),
|
|
||||||
)
|
)
|
||||||
.add_system_to_stage(
|
.add_system_to_stage(CoreStage::PostUpdate, log_visible.system());
|
||||||
CoreStage::PostUpdate,
|
|
||||||
remove_blocks_visibility
|
|
||||||
.system()
|
|
||||||
.before(UPDATE_VISIBILITY_INDEX),
|
|
||||||
)
|
|
||||||
.add_system_to_stage(
|
|
||||||
CoreStage::PostUpdate,
|
|
||||||
map_visibility_indexing
|
|
||||||
.system()
|
|
||||||
.label(UPDATE_VISIBILITY_INDEX)
|
|
||||||
.after(crate::map::UPDATE_ENTITY_INDEX_LABEL),
|
|
||||||
)
|
|
||||||
.add_system_to_stage(
|
|
||||||
CoreStage::PostUpdate,
|
|
||||||
update_viewshed_for_coordinates
|
|
||||||
.system()
|
|
||||||
.label(UPDATE_VIEWSHED)
|
|
||||||
.after(UPDATE_VISIBILITY_INDEX),
|
|
||||||
)
|
|
||||||
.add_system_to_stage(
|
|
||||||
CoreStage::PostUpdate,
|
|
||||||
update_viewshed_for_visibility_blocked
|
|
||||||
.system()
|
|
||||||
.label(UPDATE_VIEWSHED)
|
|
||||||
.after(UPDATE_VISIBILITY_INDEX),
|
|
||||||
)
|
|
||||||
.add_system_to_stage(
|
|
||||||
CoreStage::PostUpdate,
|
|
||||||
update_visible_and_revealed_tiles
|
|
||||||
.system()
|
|
||||||
.label(MAP_VISIBILITY)
|
|
||||||
.after(UPDATE_VIEWSHED),
|
|
||||||
)
|
|
||||||
.add_system_to_stage(
|
|
||||||
CoreStage::PostUpdate,
|
|
||||||
log_visible
|
|
||||||
.system()
|
|
||||||
.label(LOG_VISIBLE_LABEL)
|
|
||||||
.after(MAP_VISIBILITY),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user