Describe directions relatively.

This commit is contained in:
Nolan Darilek 2021-05-16 17:24:26 -05:00
parent 9b124e5640
commit b2138d3e4c
3 changed files with 51 additions and 12 deletions

View File

@ -1,6 +1,7 @@
use std::{ use std::{
cmp::{max, min}, cmp::{max, min},
fmt::Display, fmt::Display,
ops::Sub,
}; };
use bevy::{core::FloatOrd, prelude::*, transform::TransformSystem}; use bevy::{core::FloatOrd, prelude::*, transform::TransformSystem};
@ -94,6 +95,23 @@ impl Angle {
} }
} }
impl Sub for Angle {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
match self {
Angle::Degrees(v1) => match rhs {
Angle::Degrees(v2) => Angle::Degrees(v1 - v2),
Angle::Radians(v2) => Angle::Degrees(v1 - v2.to_degrees()),
},
Angle::Radians(v1) => match rhs {
Angle::Degrees(v2) => Angle::Radians(v1 - v2.to_radians()),
Angle::Radians(v2) => Angle::Radians(v1 - v2),
},
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)] #[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum MovementDirection { pub enum MovementDirection {
North, North,
@ -282,23 +300,42 @@ pub trait PointLike {
self.distance_squared(other).sqrt() self.distance_squared(other).sqrt()
} }
fn bearing(&self, other: &dyn PointLike) -> f32 { fn bearing(&self, other: &dyn PointLike) -> Angle {
let y = other.y() - self.y(); let y = other.y() - self.y();
let x = other.x() - self.x(); let x = other.x() - self.x();
y.atan2(x) Angle::Radians(y.atan2(x))
} }
fn direction(&self, other: &dyn PointLike) -> MovementDirection { fn direction(&self, other: &dyn PointLike) -> MovementDirection {
let heading = self.bearing(other); self.bearing(other).into()
MovementDirection::new(heading.to_degrees())
} }
fn direction_and_distance(&self, other: &dyn PointLike) -> String { fn direction_and_distance(&self, other: &dyn PointLike, yaw: Option<Angle>) -> String {
let mut tokens: Vec<String> = vec![]; let mut tokens: Vec<String> = vec![];
let distance = self.distance(other).round() as i32; let distance = self.distance(other).round() as i32;
if distance > 0 { if distance > 0 {
let tile_or_tiles = if distance == 1 { "tile" } else { "tiles" }; let tile_or_tiles = if distance == 1 { "tile" } else { "tiles" };
let direction: String = self.direction(other).into(); let direction: String = if let Some(yaw) = yaw {
let bearing = self.bearing(other);
let relative = (bearing - yaw).degrees();
match relative {
v if v <= 15. => "ahead".into(),
v if v <= 45. => "ahead and left".into(),
v if v <= 75. => "left and ahead".into(),
v if v <= 105. => "left".into(),
v if v <= 135. => "left and behind".into(),
v if v <= 165. => "behind and left".into(),
v if v <= 195. => "behind".into(),
v if v <= 225. => "behind and right".into(),
v if v <= 255. => "right and behind".into(),
v if v <= 285. => "right".into(),
v if v <= 315. => "right and ahead".into(),
v if v <= 345. => "ahead and right".into(),
_ => "ahead".into(),
}
} else {
self.direction(other).into()
};
tokens.push(format!("{} {} {}", direction, distance, tile_or_tiles)); tokens.push(format!("{} {} {}", direction, distance, tile_or_tiles));
} }
tokens.join(" ") tokens.join(" ")

View File

@ -341,7 +341,7 @@ fn exploration_changed_announcement(
} else { } else {
"Unknown".to_string() "Unknown".to_string()
}; };
let mut tokens: Vec<String> = vec![coordinates.direction_and_distance(exploring)]; let mut tokens: Vec<String> = vec![coordinates.direction_and_distance(exploring, None)];
if fog_of_war { if fog_of_war {
tokens.push("in the fog of war".into()); tokens.push("in the fog of war".into());
} }

View File

@ -6,7 +6,7 @@ use derive_more::{Deref, DerefMut};
use shadowcast::{vision_distance, Context, InputGrid}; use shadowcast::{vision_distance, Context, InputGrid};
use crate::{ use crate::{
core::{Coordinates, Player, PointLike}, core::{Angle, Coordinates, Player, PointLike},
log::Log, log::Log,
map::{ITileType, Map, MapConfig}, map::{ITileType, Map, MapConfig},
}; };
@ -222,7 +222,7 @@ fn log_visible(
mut seen: Local<HashSet<Entity>>, mut seen: Local<HashSet<Entity>>,
mut recently_lost: Local<HashMap<Entity, Timer>>, mut recently_lost: Local<HashMap<Entity, Timer>>,
mut log: Query<&mut Log>, mut log: Query<&mut Log>,
viewers: Query<(&Viewshed, &Coordinates, &Player)>, viewers: Query<(&Viewshed, &Coordinates, &Transform), With<Player>>,
map: Query<&Map>, map: Query<&Map>,
names: Query<&Name>, names: Query<&Name>,
players: Query<&Player>, players: Query<&Player>,
@ -238,7 +238,7 @@ 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, _) in viewers.iter() { for (viewshed, coordinates, transform) in viewers.iter() {
for viewed_coordinates in &viewshed.visible { for viewed_coordinates in &viewshed.visible {
for map in map.iter() { for map in map.iter() {
let index = viewed_coordinates.to_index(map.width()); let index = viewed_coordinates.to_index(map.width());
@ -250,8 +250,10 @@ fn log_visible(
if players.get(*entity).is_err() { if players.get(*entity).is_err() {
if !seen.contains(&*entity) { if !seen.contains(&*entity) {
let name = name.to_string(); let name = name.to_string();
let location = let forward = transform.local_x();
coordinates.direction_and_distance(viewed_coordinates); let yaw = Angle::Radians(forward.y.atan2(forward.x));
let location = coordinates
.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);