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::{
cmp::{max, min},
fmt::Display,
ops::Sub,
};
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)]
pub enum MovementDirection {
North,
@ -282,23 +300,42 @@ pub trait PointLike {
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 x = other.x() - self.x();
y.atan2(x)
Angle::Radians(y.atan2(x))
}
fn direction(&self, other: &dyn PointLike) -> MovementDirection {
let heading = self.bearing(other);
MovementDirection::new(heading.to_degrees())
self.bearing(other).into()
}
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 distance = self.distance(other).round() as i32;
if distance > 0 {
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.join(" ")

View File

@ -341,7 +341,7 @@ fn exploration_changed_announcement(
} else {
"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 {
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 crate::{
core::{Coordinates, Player, PointLike},
core::{Angle, Coordinates, Player, PointLike},
log::Log,
map::{ITileType, Map, MapConfig},
};
@ -222,7 +222,7 @@ fn log_visible(
mut seen: Local<HashSet<Entity>>,
mut recently_lost: Local<HashMap<Entity, Timer>>,
mut log: Query<&mut Log>,
viewers: Query<(&Viewshed, &Coordinates, &Player)>,
viewers: Query<(&Viewshed, &Coordinates, &Transform), With<Player>>,
map: Query<&Map>,
names: Query<&Name>,
players: Query<&Player>,
@ -238,7 +238,7 @@ fn log_visible(
}
let mut new_seen = HashSet::new();
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 map in map.iter() {
let index = viewed_coordinates.to_index(map.width());
@ -250,8 +250,10 @@ fn log_visible(
if players.get(*entity).is_err() {
if !seen.contains(&*entity) {
let name = name.to_string();
let location =
coordinates.direction_and_distance(viewed_coordinates);
let forward = transform.local_x();
let yaw = Angle::Radians(forward.y.atan2(forward.x));
let location = coordinates
.direction_and_distance(viewed_coordinates, Some(yaw));
log.push(format!("{}: {}", name, location));
}
new_seen.insert(*entity);