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); } #[derive(Component)] pub struct Ghost; 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(), Ghost, 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)>, ghosts: Query<&Transform, With>, ) -> OperatorStatus { let pos = ghosts.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 ghosts: Query<(&mut Transform, &TargetBerry, &BerriesEaten), With>, berries: Query<&Transform, (With, Without)>, new_berries: Query<&Transform, (With, Without, Without)>, time: Res