From 6c05e7d869f612194052b33a520cab0688207d39 Mon Sep 17 00:00:00 2001 From: PhantomMorrigan Date: Sat, 15 Nov 2025 20:36:48 +0100 Subject: [PATCH] extract ghost into its own module and plugin --- assets/{collector.png => ghost.png} | Bin src/ghost.rs | 136 ++++++++++++++++++++++++++++ src/leaderbord.rs | 2 +- src/main.rs | 133 ++------------------------- 4 files changed, 144 insertions(+), 127 deletions(-) rename assets/{collector.png => ghost.png} (100%) create mode 100644 src/ghost.rs diff --git a/assets/collector.png b/assets/ghost.png similarity index 100% rename from assets/collector.png rename to assets/ghost.png diff --git a/src/ghost.rs b/src/ghost.rs new file mode 100644 index 0000000..766744b --- /dev/null +++ b/src/ghost.rs @@ -0,0 +1,136 @@ +use bevy::prelude::*; +use bevy_bae::prelude::*; +use fake::{Fake, locales::EN}; + +use crate::{ + berries::{Berry, NewBerry}, + sample_arena, +}; + +const SPEED: f32 = 100.0; + +pub fn ghost_plugin(app: &mut App) { + app.add_systems(Startup, setup); +} + +pub fn setup(mut commands: Commands, asset_server: Res) { + commands.spawn(Camera2d); + let mut rng = rand::rng(); + + commands.spawn(( + Sprite::from_image(asset_server.load("arena.png")), + Transform::from_scale(Vec2::splat(18.0).extend(0.0)), + )); + + for _ in 1..100 { + commands.spawn(( + Plan::new(), + BerriesEaten(0), + Name::new(fake::faker::name::raw::FirstName(EN).fake::()), + Sprite::from_image(asset_server.load("ghost.png")), + Sequence, + tasks!( + Operator::new(find_closest_berry), + Operator::new(go_to_berry), + Operator::new(collect_berry) + ), + Transform::from_translation(sample_arena(&mut rng).extend(0.1)), + )); + } +} + +#[derive(Component)] +#[relationship(relationship_target = TargetedBerry)] +pub struct TargetBerry(pub Entity); + +#[derive(Component)] +#[relationship_target(relationship = TargetBerry)] +pub struct TargetedBerry(Entity); + +#[derive(Component)] +pub struct BerriesEaten(pub usize); + +fn find_closest_berry( + In(input): In, + mut commands: Commands, + berries: Query<(Entity, &Transform), (With, Without, Without)>, + planner: Query<&Transform, With>, +) -> OperatorStatus { + let pos = planner.get(input.entity).unwrap().translation.xy(); + let mut closest: Option = None; + let mut closest_dist = 0.0; + for (entity, transform) in berries { + let dist = transform.translation.xy().distance_squared(pos); + if closest.is_none() || dist < closest_dist { + closest = Some(entity); + closest_dist = dist; + } + } + + if let Some(entity) = closest { + commands.entity(input.entity).insert(TargetBerry(entity)); + return OperatorStatus::Success; + } + OperatorStatus::Ongoing +} + +fn go_to_berry( + In(input): In, + mut planners: Query<(&mut Transform, &TargetBerry, &BerriesEaten), With>, + berries: Query<&Transform, (With, Without)>, + new_berries: Query<&Transform, (With, Without, Without)>, + time: Res