Refactor helpers for direction and distance, adding some that take colliders into account.
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
parent
2d00bbb2db
commit
1721dc98f8
204
src/core.rs
204
src/core.rs
|
@ -8,7 +8,7 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use bevy::{core::FloatOrd, ecs::query::WorldQuery, prelude::*};
|
use bevy::{core::FloatOrd, ecs::query::WorldQuery, prelude::*};
|
||||||
use bevy_rapier2d::prelude::*;
|
use bevy_rapier2d::{na, parry::query::ClosestPoints, prelude::*, rapier::math::Isometry};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -52,6 +52,74 @@ impl Angle {
|
||||||
Radians(v) => *v,
|
Radians(v) => *v,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn relative_desc(&self) -> String {
|
||||||
|
let mode = RELATIVE_DIRECTION_MODE.read().unwrap();
|
||||||
|
match self.degrees() {
|
||||||
|
v if v <= 15. => "ahead",
|
||||||
|
v if v <= 45. => {
|
||||||
|
if *mode == RelativeDirectionMode::ClockFacing {
|
||||||
|
"11:00"
|
||||||
|
} else {
|
||||||
|
"ahead and left"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v if v <= 75. => {
|
||||||
|
if *mode == RelativeDirectionMode::ClockFacing {
|
||||||
|
"10:00"
|
||||||
|
} else {
|
||||||
|
"left and ahead"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v if v <= 105. => "left",
|
||||||
|
v if v <= 135. => {
|
||||||
|
if *mode == RelativeDirectionMode::ClockFacing {
|
||||||
|
"8:00"
|
||||||
|
} else {
|
||||||
|
"left and behind"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v if v <= 165. => {
|
||||||
|
if *mode == RelativeDirectionMode::ClockFacing {
|
||||||
|
"7:00"
|
||||||
|
} else {
|
||||||
|
"behind and left"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v if v <= 195. => "behind",
|
||||||
|
v if v <= 225. => {
|
||||||
|
if *mode == RelativeDirectionMode::ClockFacing {
|
||||||
|
"5:00"
|
||||||
|
} else {
|
||||||
|
"behind and right"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v if v <= 255. => {
|
||||||
|
if *mode == RelativeDirectionMode::ClockFacing {
|
||||||
|
"4:00"
|
||||||
|
} else {
|
||||||
|
"right and behind"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v if v <= 285. => "right",
|
||||||
|
v if v <= 315. => {
|
||||||
|
if *mode == RelativeDirectionMode::ClockFacing {
|
||||||
|
"2:00"
|
||||||
|
} else {
|
||||||
|
"right and ahead"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v if v <= 345. => {
|
||||||
|
if *mode == RelativeDirectionMode::ClockFacing {
|
||||||
|
"1:00"
|
||||||
|
} else {
|
||||||
|
"ahead and right"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => "ahead",
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sub for Angle {
|
impl Sub for Angle {
|
||||||
|
@ -216,6 +284,8 @@ static RELATIVE_DIRECTION_MODE: Lazy<RwLock<RelativeDirectionMode>> = Lazy::new(
|
||||||
RwLock::new(v)
|
RwLock::new(v)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
static PHYSICS_SCALE: Lazy<RwLock<f32>> = Lazy::new(|| RwLock::new(1.));
|
||||||
|
|
||||||
pub trait PointLike {
|
pub trait PointLike {
|
||||||
fn x(&self) -> f32;
|
fn x(&self) -> f32;
|
||||||
|
|
||||||
|
@ -283,73 +353,8 @@ pub trait PointLike {
|
||||||
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 = if let Some(yaw) = yaw {
|
let direction: String = if let Some(yaw) = yaw {
|
||||||
let mode = RELATIVE_DIRECTION_MODE.read().unwrap();
|
|
||||||
let bearing = self.bearing(other);
|
let bearing = self.bearing(other);
|
||||||
let relative = (bearing - yaw).degrees();
|
(bearing - yaw).relative_desc()
|
||||||
match relative {
|
|
||||||
v if v <= 15. => "ahead",
|
|
||||||
v if v <= 45. => {
|
|
||||||
if *mode == RelativeDirectionMode::ClockFacing {
|
|
||||||
"11:00"
|
|
||||||
} else {
|
|
||||||
"ahead and left"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
v if v <= 75. => {
|
|
||||||
if *mode == RelativeDirectionMode::ClockFacing {
|
|
||||||
"10:00"
|
|
||||||
} else {
|
|
||||||
"left and ahead"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
v if v <= 105. => "left",
|
|
||||||
v if v <= 135. => {
|
|
||||||
if *mode == RelativeDirectionMode::ClockFacing {
|
|
||||||
"8:00"
|
|
||||||
} else {
|
|
||||||
"left and behind"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
v if v <= 165. => {
|
|
||||||
if *mode == RelativeDirectionMode::ClockFacing {
|
|
||||||
"7:00"
|
|
||||||
} else {
|
|
||||||
"behind and left"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
v if v <= 195. => "behind",
|
|
||||||
v if v <= 225. => {
|
|
||||||
if *mode == RelativeDirectionMode::ClockFacing {
|
|
||||||
"5:00"
|
|
||||||
} else {
|
|
||||||
"behind and right"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
v if v <= 255. => {
|
|
||||||
if *mode == RelativeDirectionMode::ClockFacing {
|
|
||||||
"4:00"
|
|
||||||
} else {
|
|
||||||
"right and behind"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
v if v <= 285. => "right",
|
|
||||||
v if v <= 315. => {
|
|
||||||
if *mode == RelativeDirectionMode::ClockFacing {
|
|
||||||
"2:00"
|
|
||||||
} else {
|
|
||||||
"right and ahead"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
v if v <= 345. => {
|
|
||||||
if *mode == RelativeDirectionMode::ClockFacing {
|
|
||||||
"1:00"
|
|
||||||
} else {
|
|
||||||
"ahead and right"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => "ahead",
|
|
||||||
}
|
|
||||||
.into()
|
|
||||||
} else {
|
} else {
|
||||||
self.direction(other).into()
|
self.direction(other).into()
|
||||||
};
|
};
|
||||||
|
@ -460,6 +465,69 @@ impl From<&dyn PointLike> for (i32, i32) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait GlobalTransformExt {
|
||||||
|
fn yaw(&self) -> Angle;
|
||||||
|
fn collider_direction_and_distance(
|
||||||
|
&self,
|
||||||
|
collider: &Collider,
|
||||||
|
other: &GlobalTransform,
|
||||||
|
other_collider: &Collider,
|
||||||
|
) -> String;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GlobalTransformExt for GlobalTransform {
|
||||||
|
fn yaw(&self) -> Angle {
|
||||||
|
let forward = self.local_x();
|
||||||
|
Angle::Radians(forward.y.atan2(forward.x))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collider_direction_and_distance(
|
||||||
|
&self,
|
||||||
|
collider: &Collider,
|
||||||
|
other: &GlobalTransform,
|
||||||
|
other_collider: &Collider,
|
||||||
|
) -> String {
|
||||||
|
use bevy::math::Vec3Swizzles;
|
||||||
|
let scale = PHYSICS_SCALE.read().unwrap();
|
||||||
|
let pos1 = Isometry::new(
|
||||||
|
(self.translation / *scale).xy().into(),
|
||||||
|
self.rotation.to_scaled_axis().z,
|
||||||
|
);
|
||||||
|
let pos2 = Isometry::new(
|
||||||
|
(other.translation / *scale).xy().into(),
|
||||||
|
other.rotation.to_scaled_axis().z,
|
||||||
|
);
|
||||||
|
let closest = bevy_rapier2d::parry::query::closest_points(
|
||||||
|
&pos1,
|
||||||
|
&*collider.raw,
|
||||||
|
&pos2,
|
||||||
|
&*other_collider.raw,
|
||||||
|
f32::MAX,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let distance: u32 = match closest {
|
||||||
|
ClosestPoints::Intersecting => 0,
|
||||||
|
ClosestPoints::WithinMargin(p1, p2) => na::distance(&p1, &p2) as u32,
|
||||||
|
ClosestPoints::Disjoint => 0,
|
||||||
|
};
|
||||||
|
let tile_or_tiles = if distance == 1 { "tile" } else { "tiles" };
|
||||||
|
if distance > 0 {
|
||||||
|
if let ClosestPoints::WithinMargin(p1, p2) = closest {
|
||||||
|
let p1 = (p1.x, p1.y);
|
||||||
|
let p2 = (p2.x, p2.y);
|
||||||
|
let bearing = p1.bearing(&p2);
|
||||||
|
let yaw = self.yaw();
|
||||||
|
let direction = (bearing - yaw).relative_desc();
|
||||||
|
format!("{direction} {distance} {tile_or_tiles}")
|
||||||
|
} else {
|
||||||
|
format!("{} {}", distance, tile_or_tiles)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
format!("{} {}", distance, tile_or_tiles)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Component, Clone, Copy, Debug, Default, Reflect)]
|
#[derive(Component, Clone, Copy, Debug, Default, Reflect)]
|
||||||
#[reflect(Component)]
|
#[reflect(Component)]
|
||||||
pub struct Player;
|
pub struct Player;
|
||||||
|
@ -524,6 +592,8 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup(core_config: Res<CoreConfig>) {
|
fn setup(core_config: Res<CoreConfig>) {
|
||||||
|
let mut scale = PHYSICS_SCALE.write().unwrap();
|
||||||
|
*scale = core_config.pixels_per_unit as f32;
|
||||||
let mut mode = RELATIVE_DIRECTION_MODE.write().unwrap();
|
let mut mode = RELATIVE_DIRECTION_MODE.write().unwrap();
|
||||||
*mode = core_config.relative_direction_mode;
|
*mode = core_config.relative_direction_mode;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use bevy_tts::Tts;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
commands::RunIfExistsExt,
|
commands::RunIfExistsExt,
|
||||||
core::{Angle, CardinalDirection, Player},
|
core::{Angle, CardinalDirection, Player, GlobalTransformExt},
|
||||||
error::error_handler,
|
error::error_handler,
|
||||||
exploration::{ExplorationFocused, Exploring},
|
exploration::{ExplorationFocused, Exploring},
|
||||||
pathfinding::Destination,
|
pathfinding::Destination,
|
||||||
|
@ -264,13 +264,12 @@ where
|
||||||
fn update_direction(
|
fn update_direction(
|
||||||
mut commands: Commands,
|
mut commands: Commands,
|
||||||
mut query: Query<
|
mut query: Query<
|
||||||
(Entity, &Transform, Option<&mut CardinalDirection>),
|
(Entity, &GlobalTransform, Option<&mut CardinalDirection>),
|
||||||
(With<Player>, Changed<Transform>),
|
(With<Player>, Changed<Transform>),
|
||||||
>,
|
>,
|
||||||
) {
|
) {
|
||||||
for (entity, transform, direction) in query.iter_mut() {
|
for (entity, transform, direction) in query.iter_mut() {
|
||||||
let forward = transform.local_x();
|
let yaw = transform.yaw();
|
||||||
let yaw = Angle::Radians(forward.y.atan2(forward.x));
|
|
||||||
let new_direction: CardinalDirection = yaw.into();
|
let new_direction: CardinalDirection = yaw.into();
|
||||||
if let Some(mut direction) = direction {
|
if let Some(mut direction) = direction {
|
||||||
if *direction != new_direction {
|
if *direction != new_direction {
|
||||||
|
|
|
@ -12,7 +12,7 @@ use shadowcast::{vision_distance, Context, InputGrid};
|
||||||
use crate::{
|
use crate::{
|
||||||
bevy_rapier2d::prelude::*,
|
bevy_rapier2d::prelude::*,
|
||||||
commands::RunIfExistsExt,
|
commands::RunIfExistsExt,
|
||||||
core::{Angle, Player, PointLike},
|
core::{GlobalTransformExt, Player, PointLike},
|
||||||
log::Log,
|
log::Log,
|
||||||
map::{Map, MapConfig, MapObstruction},
|
map::{Map, MapConfig, MapObstruction},
|
||||||
};
|
};
|
||||||
|
@ -380,8 +380,8 @@ fn log_visible(
|
||||||
mut recently_lost: Local<HashMap<Entity, Timer>>,
|
mut recently_lost: Local<HashMap<Entity, Timer>>,
|
||||||
mut events: EventReader<VisibilityChanged>,
|
mut events: EventReader<VisibilityChanged>,
|
||||||
mut log: Query<&mut Log>,
|
mut log: Query<&mut Log>,
|
||||||
viewers: Query<(Entity, &Transform), (With<Player>, With<Viewshed>)>,
|
viewers: Query<(Entity, &GlobalTransform, Option<&Collider>), (With<Player>, With<Viewshed>)>,
|
||||||
visible: Query<(&Name, &Transform), Without<DontLogWhenVisible>>,
|
visible: Query<(&Name, &GlobalTransform, Option<&Collider>), Without<DontLogWhenVisible>>,
|
||||||
) {
|
) {
|
||||||
for timer in recently_lost.values_mut() {
|
for timer in recently_lost.values_mut() {
|
||||||
timer.tick(time.delta());
|
timer.tick(time.delta());
|
||||||
|
@ -392,21 +392,24 @@ fn log_visible(
|
||||||
VisibilityChanged::Gained { viewer, .. } => viewer,
|
VisibilityChanged::Gained { viewer, .. } => viewer,
|
||||||
VisibilityChanged::Lost { viewer, .. } => viewer,
|
VisibilityChanged::Lost { viewer, .. } => viewer,
|
||||||
};
|
};
|
||||||
if let Ok((viewer_entity, viewer_transform)) = viewers.get(*viewer) {
|
if let Ok((viewer_entity, viewer_transform, viewer_collider)) = viewers.get(*viewer) {
|
||||||
if let VisibilityChanged::Gained { viewed, .. } = event {
|
if let VisibilityChanged::Gained { viewed, .. } = event {
|
||||||
if *viewed == viewer_entity || recently_lost.contains_key(viewed) {
|
if *viewed == viewer_entity || recently_lost.contains_key(viewed) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Ok((name, transform)) = visible.get(*viewed) {
|
if let Ok((name, viewed_transform, viewed_collider)) = visible.get(*viewed) {
|
||||||
let viewed_coordinates = (transform.translation.x, transform.translation.y);
|
let location = if let (Some(viewer_collider), Some(viewed_collider)) =
|
||||||
let forward = viewer_transform.local_x();
|
(viewer_collider, viewed_collider)
|
||||||
let yaw = Angle::Radians(forward.y.atan2(forward.x));
|
{
|
||||||
let viewer_coordinates = (
|
viewer_transform.collider_direction_and_distance(
|
||||||
viewer_transform.translation.x,
|
viewer_collider,
|
||||||
viewer_transform.translation.y,
|
&viewed_transform,
|
||||||
);
|
viewed_collider,
|
||||||
let location =
|
)
|
||||||
viewer_coordinates.direction_and_distance(&viewed_coordinates, Some(yaw));
|
} else {
|
||||||
|
let yaw = viewer_transform.yaw();
|
||||||
|
viewer_transform.direction_and_distance(viewed_transform, Some(yaw))
|
||||||
|
};
|
||||||
if let Ok(mut log) = log.get_single_mut() {
|
if let Ok(mut log) = log.get_single_mut() {
|
||||||
log.push(format!("{}: {location}", name));
|
log.push(format!("{}: {location}", name));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user