diff --git a/src/head_drop.rs b/src/head_drop.rs index b8148ce..9375f0a 100644 --- a/src/head_drop.rs +++ b/src/head_drop.rs @@ -4,7 +4,10 @@ use crate::{ squish_animation::SquishAnimation, tb_entities::SecretHead, }; use avian3d::prelude::*; -use bevy::prelude::*; +use bevy::{ + ecs::{relationship::RelatedSpawner, spawn::SpawnWith}, + prelude::*, +}; use std::f32::consts::PI; #[derive(Event, Reflect)] @@ -44,7 +47,6 @@ struct SecretHeadMarker; pub struct HeadCollected(pub usize); pub fn plugin(app: &mut App) { - app.add_systems(Update, collect_head.run_if(in_state(GameState::Playing))); app.add_systems(OnEnter(GameState::Playing), spawn); global_observer!(app, on_head_drop); @@ -85,6 +87,8 @@ fn on_head_drop( } .ok_or("asset not found")?; + let head_id = drop.head_id; + commands .spawn(( Name::new("headdrop"), @@ -97,15 +101,18 @@ fn on_head_drop( GameLayer::CollectiblePhysics, LayerMask::ALL & !GameLayer::Player.to_bits(), ), - CollisionEventsEnabled, Restitution::new(0.6), - children![( - Collider::sphere(1.5), - CollisionLayers::new(GameLayer::CollectibleSensors, GameLayer::Player), - Sensor, - CollisionEventsEnabled, - HeadDrop(drop.head_id), - )], + Children::spawn(SpawnWith(move |parent: &mut RelatedSpawner| { + parent + .spawn(( + Collider::sphere(1.5), + CollisionLayers::new(GameLayer::CollectibleSensors, GameLayer::Player), + Sensor, + CollisionEventsEnabled, + HeadDrop(head_id), + )) + .observe(on_collect_head); + })), )) .insert_if( ExternalImpulse::new(spawn_dir * 180.).with_persistence(false), @@ -120,23 +127,18 @@ fn on_head_drop( Ok(()) } -fn collect_head( +fn on_collect_head( + trigger: Trigger, mut commands: Commands, - mut collision_event_reader: EventReader, query_player: Query<&Player>, query_collectable: Query<(&HeadDrop, &ChildOf)>, query_secret: Query<&SecretHeadMarker>, ) { - for CollisionStarted(e1, e2) in collision_event_reader.read() { - let collectable = if query_player.contains(*e1) && query_collectable.contains(*e2) { - *e2 - } else if query_player.contains(*e2) && query_collectable.contains(*e1) { - *e1 - } else { - continue; - }; + let collectable = trigger.target(); + let collider = trigger.collider; - let (key, child_of) = query_collectable.get(collectable).unwrap(); + if query_player.contains(collider) { + let (drop, child_of) = query_collectable.get(collectable).unwrap(); let is_secret = query_secret.contains(collectable); @@ -145,7 +147,8 @@ fn collect_head( } else { commands.trigger(PlaySound::HeadCollect); } - commands.trigger(HeadCollected(key.0)); + + commands.trigger(HeadCollected(drop.0)); commands.entity(child_of.parent()).despawn(); } } diff --git a/src/keys.rs b/src/keys.rs index b382306..1f7a45d 100644 --- a/src/keys.rs +++ b/src/keys.rs @@ -1,10 +1,12 @@ use crate::{ - GameState, billboards::Billboard, global_observer, loading_assets::GameAssets, - physics_layers::GameLayer, player::Player, sounds::PlaySound, - squish_animation::SquishAnimation, + billboards::Billboard, global_observer, loading_assets::GameAssets, physics_layers::GameLayer, + player::Player, sounds::PlaySound, squish_animation::SquishAnimation, }; use avian3d::prelude::*; -use bevy::prelude::*; +use bevy::{ + ecs::{relationship::RelatedSpawner, spawn::SpawnWith}, + prelude::*, +}; use std::f32::consts::PI; #[derive(Event, Reflect)] @@ -18,14 +20,14 @@ struct Key(pub String); pub struct KeyCollected(pub String); pub fn plugin(app: &mut App) { - app.add_systems(Update, collect_key.run_if(in_state(GameState::Playing))); - global_observer!(app, on_spawn_key); } fn on_spawn_key(trigger: Trigger, mut commands: Commands, assets: Res) { let KeySpawn(position, id) = trigger.event(); + let id = id.clone(); + let angle = rand::random::() * PI * 2.; let spawn_dir = Quat::from_rotation_y(angle) * Vec3::new(0.5, 0.6, 0.).normalize(); @@ -38,41 +40,39 @@ fn on_spawn_key(trigger: Trigger, mut commands: Commands, assets: Res< LockedAxes::ROTATION_LOCKED, RigidBody::Dynamic, CollisionLayers::new(GameLayer::CollectiblePhysics, GameLayer::Level), - CollisionEventsEnabled, Restitution::new(0.6), - children![ - ( + Children::spawn(( + Spawn(( Billboard, SquishAnimation(2.6), SceneRoot(assets.mesh_key.clone()), - ), - ( - Collider::sphere(1.5), - CollisionLayers::new(GameLayer::CollectibleSensors, GameLayer::Player), - Sensor, - CollisionEventsEnabled, - Key(id.clone()), - ) - ], + )), + SpawnWith(|parent: &mut RelatedSpawner| { + parent + .spawn(( + Collider::sphere(1.5), + CollisionLayers::new(GameLayer::CollectibleSensors, GameLayer::Player), + Sensor, + CollisionEventsEnabled, + Key(id), + )) + .observe(on_collect_key); + }), + )), )); } -fn collect_key( +fn on_collect_key( + trigger: Trigger, mut commands: Commands, - mut collision_event_reader: EventReader, query_player: Query<&Player>, query_collectable: Query<(&Key, &ChildOf)>, ) { - for CollisionStarted(e1, e2) in collision_event_reader.read() { - let collectable = if query_player.contains(*e1) && query_collectable.contains(*e2) { - *e2 - } else if query_player.contains(*e2) && query_collectable.contains(*e1) { - *e1 - } else { - continue; - }; + let key = trigger.target(); + let collider = trigger.collider; - let (key, child_of) = query_collectable.get(collectable).unwrap(); + if query_player.contains(collider) { + let (key, child_of) = query_collectable.get(key).unwrap(); commands.trigger(PlaySound::KeyCollect); commands.trigger(KeyCollected(key.0.clone()));