diff --git a/src/game.rs b/src/game.rs index b5c803e..8da2492 100644 --- a/src/game.rs +++ b/src/game.rs @@ -57,6 +57,8 @@ impl Plugin for GamePlugin { .with_system(character_particle_effect_system) .with_system(move_win_text_system), ) + .add_system_to_stage(CoreStage::PostUpdate, char_char_collision_event_system) + .add_system_to_stage(CoreStage::PostUpdate, char_airbound_event_system) .add_system_to_stage(CoreStage::PostUpdate, collision_event_system); } } @@ -102,7 +104,10 @@ pub struct CharacterColor(pub Color); pub struct Player; #[derive(Component)] -pub struct CollisionCount(usize); +pub struct Platform; + +#[derive(Component)] +pub struct Airbound(bool); #[derive(Component)] pub struct Melty(pub Color); @@ -190,7 +195,7 @@ pub fn spawn_character( .insert(Sensor) .insert(Collider::cuboid(30., 0.5)) .insert(ActiveEvents::COLLISION_EVENTS) - .insert(CollisionCount(0)); + .insert(Airbound(true)); }); character_list.0.insert(entity_commands.id()); @@ -231,7 +236,8 @@ pub fn spawn_platform( ..default() }) .insert(Collider::cuboid(size.x / 2., size.y / 2.)) - .insert(Level); + .insert(Level) + .insert(Platform); } pub fn spawn_melty_platform( @@ -267,9 +273,113 @@ pub fn spawn_melty_platform( }); } +fn char_char_collision_event_system( + mut commands: Commands, + + mut collision_events: EventReader, + character_query: Query<( + &mut CharacterColor, + &Transform, + &mut Handle, + Option<&Player>, + )>, + + mut character_list: ResMut, + mut app_state: ResMut>, + character_meshes: Res, + audio: Res>, + mut materials: ResMut>, +) { + for collision_event in collision_events.iter() { + if let CollisionEvent::Started(e1, e2, _flags) = collision_event { + if let ( + Ok((c1_color, c1_transform, _c1_material, c1_player)), + Ok((c2_color, c2_transform, _c2_material, c2_player)), + ) = (character_query.get(*e1), character_query.get(*e2)) { + character_list.0.remove(e1); + character_list.0.remove(e2); + commands.entity(*e1).despawn_recursive(); + commands.entity(*e2).despawn_recursive(); + + let new_color = (Vec4::from(c1_color.0) + Vec4::from(c2_color.0)) + .clamp(Vec4::ZERO, Vec4::ONE); + + // If color approximately white + if app_state.current() == &AppState::Game && new_color.min_element() >= 0.9 { + app_state.replace(AppState::Win).ok(); + } + + // position character based on current player location + spawn_character( + &mut commands, + &character_meshes, + &mut materials, + &audio, + &mut character_list, + if c1_player.is_some() { + *c1_transform + } else if c2_player.is_some() { + *c2_transform + } else { + Transform::identity().with_translation( + (c1_transform.translation + c2_transform.translation) * 0.5, + ) + }, + new_color.into(), + c1_player.is_some() || c2_player.is_some(), + ); + + audio.send(AudioMsg::Fusion).ok(); + } + } + } +} + +fn char_airbound_event_system( + mut collision_events: EventReader, + mut airbound_query: Query<&mut Airbound>, + platform_query: Query<&Platform>, +) { + // detect platform + player collisions only + for collision_event in collision_events.iter() { + match collision_event { + CollisionEvent::Started(e1, e2, flags) => { + if *flags == CollisionEventFlags::SENSOR { + if let (Ok(mut airbound), Ok(_)) = ( + airbound_query.get_mut(*e1), + platform_query.get(*e2), + ) { + airbound.0 = false; + } else if let (Ok(mut airbound), Ok(_)) = ( + airbound_query.get_mut(*e2), + platform_query.get(*e1), + ) { + airbound.0 = false; + } + } + } + + CollisionEvent::Stopped(e1, e2, flags) => { + if *flags == CollisionEventFlags::SENSOR { + if let (Ok(mut airbound), Ok(_)) = ( + airbound_query.get_mut(*e1), + platform_query.get(*e2), + ) { + airbound.0 = true; + } else if let (Ok(mut airbound), Ok(_)) = ( + airbound_query.get_mut(*e2), + platform_query.get(*e1), + ) { + airbound.0 = true; + } + } + } + } + } +} + fn collision_event_system( mut commands: Commands, - character_meshes: Res, mut materials: ResMut>, mut collision_events: EventReader, mut character_query: Query<( @@ -280,134 +390,64 @@ fn collision_event_system( )>, pass_through_filter_query: Query<&PassThroughFilter>, melty_query: Query<&Melty>, - mut collision_counter_query: Query<&mut CollisionCount>, - mut app_state: ResMut>, audio: Res>, - mut character_list: ResMut, ) { for collision_event in collision_events.iter() { - match collision_event { - CollisionEvent::Started(e1, e2, flags) => { - if flags.is_empty() { - if let ( - Ok((c1_color, c1_transform, _c1_material, c1_player)), - Ok((c2_color, c2_transform, _c2_material, c2_player)), - ) = (character_query.get(*e1), character_query.get(*e2)) - { - character_list.0.remove(e1); - character_list.0.remove(e2); - commands.entity(*e1).despawn_recursive(); - commands.entity(*e2).despawn_recursive(); + if let CollisionEvent::Started(e1, e2, flags) = collision_event { + if flags.is_empty() { + if let (Ok((c_color, _c_transform, _c_material, _c_player)), Ok(melty)) = + (character_query.get_mut(*e1), melty_query.get(*e2)) + { + if (Vec4::from(melty.0) - Vec4::from(c_color.0)).max_element() <= 0. { + commands.entity(*e2).despawn_recursive(); + } + } else if let (Ok((c_color, _c_transform, _c_material, _c_player)), Ok(melty)) = + (character_query.get_mut(*e2), melty_query.get(*e1)) + { + if (Vec4::from(melty.0) - Vec4::from(c_color.0)).max_element() <= 0. { + commands.entity(*e1).despawn_recursive(); + } + } + } else if *flags == CollisionEventFlags::SENSOR { + if let (Ok((mut c_color, _c_transform, mut c_material, c_player)), Ok(filter)) = ( + character_query.get_mut(*e1), + pass_through_filter_query.get(*e2), + ) { + c_color.0 = filter.apply(c_color.0); + *c_material = materials.add(ColorMaterial::from(c_color.0)); - let new_color = (Vec4::from(c1_color.0) + Vec4::from(c2_color.0)) - .clamp(Vec4::ZERO, Vec4::ONE); + if c_player.is_some() { + audio + .send(AudioMsg::Color([ + c_color.0.r(), + c_color.0.g(), + c_color.0.b(), + ])) + .ok(); + audio.send(AudioMsg::Switch).ok(); + } + } else if let ( + Ok((mut c_color, _c_transform, mut c_material, c_player)), + Ok(filter), + ) = ( + character_query.get_mut(*e2), + pass_through_filter_query.get(*e1), + ) { + c_color.0 = filter.apply(c_color.0); + *c_material = materials.add(ColorMaterial::from(c_color.0)); - // If color approximately white - if app_state.current() == &AppState::Game && new_color.min_element() >= 0.9 - { - app_state.replace(AppState::Win).ok(); - } - - // position character based on current player location - spawn_character( - &mut commands, - &character_meshes, - &mut materials, - &audio, - &mut character_list, - if c1_player.is_some() { - *c1_transform - } else if c2_player.is_some() { - *c2_transform - } else { - Transform::identity().with_translation( - (c1_transform.translation + c2_transform.translation) / 2., - ) - }, - new_color.into(), - c1_player.is_some() || c2_player.is_some(), - ); - - audio.send(AudioMsg::Fusion).ok(); - } else if let (Ok((c_color, _c_transform, _c_material, _c_player)), Ok(melty)) = - (character_query.get_mut(*e1), melty_query.get(*e2)) - { - if (Vec4::from(melty.0) - Vec4::from(c_color.0)).max_element() <= 0. { - commands.entity(*e2).despawn_recursive(); - } - } else if let (Ok((c_color, _c_transform, _c_material, _c_player)), Ok(melty)) = - (character_query.get_mut(*e2), melty_query.get(*e1)) - { - if (Vec4::from(melty.0) - Vec4::from(c_color.0)).max_element() <= 0. { - commands.entity(*e1).despawn_recursive(); - } - } - } else if *flags == CollisionEventFlags::SENSOR { - if let (Ok((mut c_color, _c_transform, mut c_material, c_player)), Ok(filter)) = ( - character_query.get_mut(*e1), - pass_through_filter_query.get(*e2), - ) { - c_color.0 = filter.apply(c_color.0); - *c_material = materials.add(ColorMaterial::from(c_color.0)); - - if c_player.is_some() { - audio - .send(AudioMsg::Color([ - c_color.0.r(), - c_color.0.g(), - c_color.0.b(), - ])) - .ok(); - audio.send(AudioMsg::Switch).ok(); - } - } else if let ( - Ok((mut c_color, _c_transform, mut c_material, c_player)), - Ok(filter), - ) = ( - character_query.get_mut(*e2), - pass_through_filter_query.get(*e1), - ) { - c_color.0 = filter.apply(c_color.0); - *c_material = materials.add(ColorMaterial::from(c_color.0)); - - if c_player.is_some() { - audio - .send(AudioMsg::Color([ - c_color.0.r(), - c_color.0.g(), - c_color.0.b(), - ])) - .ok(); - audio.send(AudioMsg::Switch).ok(); - } - } else if let (Ok(mut collision_count), Err(_)) = ( - collision_counter_query.get_mut(*e1), - character_query.get_mut(*e2), - ) { - collision_count.0 += 1; - } else if let (Ok(mut collision_count), Err(_)) = ( - collision_counter_query.get_mut(*e2), - character_query.get_mut(*e1), - ) { - collision_count.0 += 1; - } - } - } - CollisionEvent::Stopped(e1, e2, flags) => { - if *flags == CollisionEventFlags::SENSOR { - if let (Ok(mut collision_count), Err(_)) = ( - collision_counter_query.get_mut(*e1), - character_query.get_mut(*e2), - ) { - collision_count.0 = collision_count.0.saturating_sub(1); - } else if let (Ok(mut collision_count), Err(_)) = ( - collision_counter_query.get_mut(*e2), - character_query.get_mut(*e1), - ) { - collision_count.0 = collision_count.0.saturating_sub(1); - } - } - } + if c_player.is_some() { + audio + .send(AudioMsg::Color([ + c_color.0.r(), + c_color.0.g(), + c_color.0.b(), + ])) + .ok(); + audio.send(AudioMsg::Switch).ok(); + } + } + } } } } @@ -450,7 +490,7 @@ fn change_character_system( fn player_movement_system( keyboard_input: Res>, mut characters: Query<(&mut Velocity, &Children), With>, - collision_counter_query: Query<&CollisionCount>, + airbound_query: Query<&Airbound>, audio: Res>, ) { let right_pressed: bool = @@ -461,9 +501,8 @@ fn player_movement_system( for (mut velocity, children) in characters.iter_mut() { velocity.linvel.x = 200. * (right_pressed as i8 - left_pressed as i8) as f32; - if keyboard_input.just_pressed(KeyCode::Space) - && collision_counter_query.get(children[0]).unwrap().0 != 0 - { + let airbound: &Airbound = airbound_query.get(children[0]).unwrap(); + if keyboard_input.just_pressed(KeyCode::Space) && !airbound.0 { audio.send(AudioMsg::Jump).ok(); velocity.linvel.y = 700.; }