Compare commits

..

No commits in common. "bd899b9c8e1a1fa7ded812fc2c508635d514937b" and "1721dc98f85050ffbf5999c36f7d071c3a0751cc" have entirely different histories.

3 changed files with 56 additions and 63 deletions

View File

@ -8,12 +8,7 @@ use std::{
}; };
use bevy::{core::FloatOrd, ecs::query::WorldQuery, prelude::*}; use bevy::{core::FloatOrd, ecs::query::WorldQuery, prelude::*};
use bevy_rapier2d::{ use bevy_rapier2d::{na, parry::query::ClosestPoints, prelude::*, rapier::math::Isometry};
na,
parry::query::ClosestPoints,
prelude::*,
rapier::{math::Isometry, prelude::AABB},
};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use rand::prelude::*; use rand::prelude::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -533,9 +528,6 @@ impl GlobalTransformExt for GlobalTransform {
} }
} }
#[derive(Component, Copy, Clone, Debug, Deref, DerefMut, PartialEq)]
pub struct Area(pub AABB);
#[derive(Component, Clone, Copy, Debug, Default, Reflect)] #[derive(Component, Clone, Copy, Debug, Default, Reflect)]
#[reflect(Component)] #[reflect(Component)]
pub struct Player; pub struct Player;

View File

@ -4,6 +4,7 @@ use bevy::prelude::*;
use bevy_rapier2d::{ use bevy_rapier2d::{
na::{Isometry2, Vector2}, na::{Isometry2, Vector2},
prelude::*, prelude::*,
rapier::prelude::AABB,
}; };
pub use here_be_dragons::Map as MapgenMap; pub use here_be_dragons::Map as MapgenMap;
use here_be_dragons::{geometry::Rect as MRect, MapFilter, Tile}; use here_be_dragons::{geometry::Rect as MRect, MapFilter, Tile};
@ -11,11 +12,16 @@ use maze_generator::{prelude::*, recursive_backtracking::RbGenerator};
use rand::prelude::StdRng; use rand::prelude::StdRng;
use crate::{ use crate::{
core::{Area, PointLike}, core::{Player, PointLike},
exploration::Mappable, exploration::Mappable,
log::Log,
utils::target_and_other,
visibility::Visible, visibility::Visible,
}; };
#[derive(Component, Copy, Clone, Debug, Deref, DerefMut, PartialEq)]
pub struct Area(pub AABB);
#[derive(Component, Clone, Default, Deref, DerefMut)] #[derive(Component, Clone, Default, Deref, DerefMut)]
pub struct Map<D: 'static + Clone + Default + Send + Sync>(pub MapgenMap<D>); pub struct Map<D: 'static + Clone + Default + Send + Sync>(pub MapgenMap<D>);
@ -80,12 +86,16 @@ impl ITileType for Tile {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct MapConfig { pub struct MapConfig {
pub describe_undescribed_areas: bool,
pub speak_area_descriptions: bool,
pub start_revealed: bool, pub start_revealed: bool,
} }
impl Default for MapConfig { impl Default for MapConfig {
fn default() -> Self { fn default() -> Self {
Self { Self {
describe_undescribed_areas: false,
speak_area_descriptions: true,
start_revealed: false, start_revealed: false,
} }
} }
@ -314,6 +324,44 @@ fn spawn_portal_colliders<D: 'static + Clone + Default + Send + Sync>(
} }
} }
fn area_description(
mut events: EventReader<CollisionEvent>,
areas: Query<(&Area, Option<&Name>)>,
players: Query<&Player>,
config: Res<MapConfig>,
mut log: Query<&mut Log>,
) {
for event in events.iter() {
let (entity1, entity2, started) = match event {
CollisionEvent::Started(collider1, collider2, _) => (collider1, collider2, true),
CollisionEvent::Stopped(collider1, collider2, _) => (collider1, collider2, false),
};
if let Some((area, other)) = target_and_other(*entity1, *entity2, &|v| areas.get(v).is_ok())
{
if players.get(other).is_ok() {
if let Ok((aabb, area_name)) = areas.get(area) {
let name = if let Some(name) = area_name {
Some(name.to_string())
} else if config.describe_undescribed_areas {
Some(format!("{}-by-{} area", aabb.extents().x, aabb.extents().y))
} else {
None
};
if let Some(name) = name {
if let Ok(mut log) = log.get_single_mut() {
if started {
log.push(format!("Entering {name}."));
} else {
log.push(format!("Leaving {name}."));
}
}
}
}
}
}
}
}
pub struct MapPlugin<D: 'static + Clone + Default + Send + Sync>(PhantomData<D>); pub struct MapPlugin<D: 'static + Clone + Default + Send + Sync>(PhantomData<D>);
impl<D: 'static + Clone + Default + Send + Sync> Default for MapPlugin<D> { impl<D: 'static + Clone + Default + Send + Sync> Default for MapPlugin<D> {
@ -327,9 +375,13 @@ impl<D: 'static + Clone + Default + Send + Sync> Plugin for MapPlugin<D> {
if !app.world.contains_resource::<MapConfig>() { if !app.world.contains_resource::<MapConfig>() {
app.insert_resource(MapConfig::default()); app.insert_resource(MapConfig::default());
} }
let config = app.world.get_resource::<MapConfig>().unwrap().clone();
app.register_type::<Portal>() app.register_type::<Portal>()
.add_system_to_stage(CoreStage::PreUpdate, spawn_colliders::<D>) .add_system_to_stage(CoreStage::PreUpdate, spawn_colliders::<D>)
.add_system_to_stage(CoreStage::PreUpdate, spawn_portals::<D>) .add_system_to_stage(CoreStage::PreUpdate, spawn_portals::<D>)
.add_system_to_stage(CoreStage::PreUpdate, spawn_portal_colliders::<D>); .add_system_to_stage(CoreStage::PreUpdate, spawn_portal_colliders::<D>);
if config.speak_area_descriptions {
app.add_system_to_stage(CoreStage::PostUpdate, area_description);
}
} }
} }

View File

@ -7,12 +7,10 @@ use bevy_tts::Tts;
use crate::{ use crate::{
commands::RunIfExistsExt, commands::RunIfExistsExt,
core::{Angle, Area, CardinalDirection, GlobalTransformExt, Player}, core::{Angle, CardinalDirection, Player, GlobalTransformExt},
error::error_handler, error::error_handler,
exploration::{ExplorationFocused, Exploring}, exploration::{ExplorationFocused, Exploring},
log::Log,
pathfinding::Destination, pathfinding::Destination,
utils::target_and_other,
}; };
#[derive(Component, Clone, Copy, Debug, Deref, DerefMut, Reflect)] #[derive(Component, Clone, Copy, Debug, Deref, DerefMut, Reflect)]
@ -324,50 +322,6 @@ fn remove_speed(removed: RemovedComponents<Speed>, mut query: Query<&mut Velocit
} }
} }
fn log_area_descriptions<S, A>(
mut events: EventReader<CollisionEvent>,
areas: Query<(&Area, Option<&Name>)>,
players: Query<&Player>,
config: Res<NavigationConfig<S, A>>,
mut log: Query<&mut Log>,
) where
S: 'static + Send + Sync,
A: 'static + Send + Sync,
{
if !config.log_area_descriptions {
return;
}
for event in events.iter() {
let (entity1, entity2, started) = match event {
CollisionEvent::Started(collider1, collider2, _) => (collider1, collider2, true),
CollisionEvent::Stopped(collider1, collider2, _) => (collider1, collider2, false),
};
if let Some((area, other)) = target_and_other(*entity1, *entity2, &|v| areas.get(v).is_ok())
{
if players.get(other).is_ok() {
if let Ok((aabb, area_name)) = areas.get(area) {
let name = if let Some(name) = area_name {
Some(name.to_string())
} else if config.describe_undescribed_areas {
Some(format!("{}-by-{} area", aabb.extents().x, aabb.extents().y))
} else {
None
};
if let Some(name) = name {
if let Ok(mut log) = log.get_single_mut() {
if started {
log.push(format!("Entering {name}."));
} else {
log.push(format!("Leaving {name}."));
}
}
}
}
}
}
}
}
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct NavigationConfig<S, A> { pub struct NavigationConfig<S, A> {
pub action_backward: Option<A>, pub action_backward: Option<A>,
@ -386,8 +340,6 @@ pub struct NavigationConfig<S, A> {
pub strafe_movement_factor: f32, pub strafe_movement_factor: f32,
pub sprint_movement_factor: f32, pub sprint_movement_factor: f32,
pub movement_control_states: Vec<S>, pub movement_control_states: Vec<S>,
pub describe_undescribed_areas: bool,
pub log_area_descriptions: bool,
} }
impl<S, A> Default for NavigationConfig<S, A> { impl<S, A> Default for NavigationConfig<S, A> {
@ -409,8 +361,6 @@ impl<S, A> Default for NavigationConfig<S, A> {
strafe_movement_factor: 1., strafe_movement_factor: 1.,
sprint_movement_factor: 3., sprint_movement_factor: 3.,
movement_control_states: vec![], movement_control_states: vec![],
describe_undescribed_areas: false,
log_area_descriptions: true,
} }
} }
} }
@ -446,8 +396,7 @@ where
.add_system_to_stage(CoreStage::PostUpdate, remove_direction) .add_system_to_stage(CoreStage::PostUpdate, remove_direction)
.add_system(speak_direction.chain(error_handler)) .add_system(speak_direction.chain(error_handler))
.add_system(add_speed) .add_system(add_speed)
.add_system_to_stage(CoreStage::PostUpdate, remove_speed) .add_system_to_stage(CoreStage::PostUpdate, remove_speed);
.add_system_to_stage(CoreStage::PostUpdate, log_area_descriptions::<S, A>);
const MOVEMENT_CONTROLS: &str = "MOVEMENT_CONTROLS"; const MOVEMENT_CONTROLS: &str = "MOVEMENT_CONTROLS";
if config.movement_control_states.is_empty() { if config.movement_control_states.is_empty() {
app.add_system(movement_controls::<S, A>.label(MOVEMENT_CONTROLS)) app.add_system(movement_controls::<S, A>.label(MOVEMENT_CONTROLS))