Skip to content

Commit

Permalink
impr: target to hold a position not an entity
Browse files Browse the repository at this point in the history
  • Loading branch information
lgrossi committed May 8, 2024
1 parent 518e4cd commit ef5953a
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 37 deletions.
4 changes: 2 additions & 2 deletions crates/ryot_brain/examples/pathfinding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ fn main() {
..default()
})
.add_pathable::<TilePosition, Flags>()
.add_systems(Startup, (spawn_basic))
.add_systems(Startup, spawn_basic)
.add_plugins(BigBrainPlugin::new(PreUpdate))
.add_systems(
PreUpdate,
Expand Down Expand Up @@ -86,7 +86,7 @@ fn spawn_basic(mut commands: Commands) {
.label("ChaserThinker")
.picker(FirstToScore::new(0.6))
.find_path::<Target>()
.follows_path_with_fallback(MovesRandomly),
.follows_path_with_fallback(1., MovesRandomly),
));
}
}
Expand Down
31 changes: 11 additions & 20 deletions crates/ryot_brain/src/find_closest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use big_brain::actions::ActionState;
use big_brain::prelude::*;
use derive_more::{Deref, DerefMut};
use ryot_core::prelude::*;
use ryot_pathfinder::prelude::*;
use ryot_tiled::prelude::*;
use ryot_utils::prelude::*;
use std::fmt::Debug;
Expand All @@ -13,7 +12,7 @@ use std::time::Duration;
pub trait Thinking = Clone + Debug + ThreadSafe;

#[derive(Clone, Copy, Component, Debug, Deref, DerefMut)]
pub struct Target(Entity);
pub struct Target(pub TilePosition);

pub trait PathFindingThinker {
fn find_path<T: Thinking>(self) -> Self;
Expand All @@ -31,7 +30,7 @@ impl PathFindingThinker for ThinkerBuilder {
}

#[derive(Clone, Component, Debug, ScorerBuilder)]
pub struct FindTargetScorer<T: Thinking>(Timer, PhantomData<T>);
pub struct FindTargetScorer<T: Thinking>(pub Timer, PhantomData<T>);

impl<T: Thinking> Default for FindTargetScorer<T> {
fn default() -> Self {
Expand Down Expand Up @@ -92,7 +91,7 @@ pub fn find_closest_target<T: Component + Thinking>(
let actor_position = positions.get(*actor).expect("actor has no position");
let closest_target = get_closest_target(actor_position, &q_target_positions);

let Some((target, closest_target)) = closest_target else {
let Some((_, closest_target)) = closest_target else {
debug!("No closest target found, failing.");
*action_state = ActionState::Cancelled;
continue;
Expand All @@ -101,8 +100,6 @@ pub fn find_closest_target<T: Component + Thinking>(
let target_pos = get_closest_valid_surrounding_position(
&closest_target,
actor_position,
1,
2,
&flags_cache,
);

Expand All @@ -125,7 +122,7 @@ pub fn find_closest_target<T: Component + Thinking>(
};

cmd.entity(*actor).insert((
Target(target),
Target(target_pos),
TiledPathFindingQuery::new(target_pos)
.with_success_range((0., 0.))
.with_timeout(Duration::from_secs(2)),
Expand Down Expand Up @@ -160,23 +157,17 @@ fn get_closest_target<T: Component>(
fn get_closest_valid_surrounding_position(
destination_pos: &TilePosition,
actor_pos: &TilePosition,
cardinal_cost: u32,
diagonal_cost: u32,
flags_cache: &Res<Cache<TilePosition, Flags>>,
) -> Option<TilePosition> {
let surrounding_positions = weighted_neighbors_2d_generator(
destination_pos,
&|pos| pos.is_navigable(flags_cache) || pos == actor_pos,
cardinal_cost,
diagonal_cost,
);

surrounding_positions
destination_pos
.get_surroundings()
.iter()
.filter(|&pos| pos.is_navigable(flags_cache) || pos == actor_pos)
.map(|&pos| (pos, pos.distance(actor_pos)))
.min_by(|(a, a_weight), (b, b_weight)| {
(a.distance(actor_pos) * *a_weight as f32)
.partial_cmp(&(b.distance(actor_pos) * *b_weight as f32))
(a.distance(actor_pos) * *a_weight)
.partial_cmp(&(b.distance(actor_pos) * *b_weight))
.unwrap()
})
.map(|(pos, _)| *pos)
.map(|(pos, _)| pos)
}
39 changes: 24 additions & 15 deletions crates/ryot_brain/src/follow_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,31 @@ use ryot_core::prelude::*;
use ryot_pathfinder::prelude::*;
use ryot_tiled::prelude::*;
use ryot_utils::prelude::*;
use std::ops::Deref;

pub trait PathFollowingThinker {
fn follows_path(self) -> Self;
fn follows_path_with_fallback(self, default: impl ActionBuilder + 'static) -> Self;
fn follows_path(self, duration_sec: f32) -> Self;
fn follows_path_with_fallback(
self,
duration_sec: f32,
default: impl ActionBuilder + 'static,
) -> Self;
}

impl PathFollowingThinker for ThinkerBuilder {
fn follows_path(self) -> Self {
fn follows_path(self, duration_sec: f32) -> Self {
self.when(
FollowPathScore::default(),
FollowPathScore::with_duration_in_seconds(duration_sec),
Steps::build().label("FollowPath").step(FollowPath),
)
}

fn follows_path_with_fallback(self, default: impl ActionBuilder + 'static) -> Self {
fn follows_path_with_fallback(
self,
duration_sec: f32,
default: impl ActionBuilder + 'static,
) -> Self {
self.when(
FollowPathScore::default(),
FollowPathScore::with_duration_in_seconds(duration_sec),
Steps::build()
.label("FollowPath")
.step(FollowPath)
Expand All @@ -34,11 +41,17 @@ impl PathFollowingThinker for ThinkerBuilder {
}

#[derive(Clone, Component, Debug, ScorerBuilder)]
pub struct FollowPathScore(Timer);
pub struct FollowPathScore(pub Timer);

impl Default for FollowPathScore {
fn default() -> Self {
Self(Timer::from_seconds(1., TimerMode::Repeating))
Self::with_duration_in_seconds(1.)
}
}

impl FollowPathScore {
fn with_duration_in_seconds(duration: f32) -> Self {
Self(Timer::from_seconds(duration, TimerMode::Repeating))
}
}

Expand All @@ -54,12 +67,8 @@ pub fn follow_path_scorer(
for (Actor(actor), mut score, mut scorer) in &mut query {
let actor_position = positions.get(*actor).expect("actor has no position");

let is_far_from_target = targets.get(*actor).map_or(true, |target| {
let target_position = positions
.get(*target.deref())
.expect("target has no position");

actor_position.distance(target_position) > 1.42
let is_far_from_target = targets.get(*actor).map_or(true, |target_position| {
actor_position.distance(target_position) > 0.
});

if scorer.0.tick(time.delta()).just_finished() && is_far_from_target {
Expand Down
17 changes: 17 additions & 0 deletions crates/ryot_tiled/src/map/position/interactions.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::prelude::*;
use glam::IVec3;
use ryot_core::prelude::Point;
use std::collections::HashSet;

Expand Down Expand Up @@ -33,4 +34,20 @@ impl TilePosition {

true
}

pub fn get_surroundings(&self) -> Vec<TilePosition> {
let mut surroundings = Vec::with_capacity(8);

for x in -1..=1 {
for y in -1..=1 {
if x == 0 && y == 0 {
continue;
}

surroundings.push(TilePosition(self.0 + IVec3::new(x, y, 0)));
}
}

surroundings
}
}

0 comments on commit ef5953a

Please sign in to comment.