Describe directions relatively.
This commit is contained in:
parent
9b124e5640
commit
b2138d3e4c
49
src/core.rs
49
src/core.rs
|
@ -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(" ")
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user