diff --git a/README.md b/README.md index abc7271..65737f5 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,9 @@ * despawn black characters * despawn character when too far * level design -* (?) can jump only from a surface (no mid-air jump) * (?) multiplayer * more audio +* "jumpable" component to avoid jumping on sensors ## Build diff --git a/src/game.rs b/src/game.rs index e1499b3..6cdd7cd 100644 --- a/src/game.rs +++ b/src/game.rs @@ -93,6 +93,9 @@ pub struct CharacterColor(pub Color); #[derive(Component)] pub struct Player; +#[derive(Component)] +pub struct CollisionCount(usize); + // Systems fn setup( @@ -161,7 +164,16 @@ pub fn spawn_character( linear_damping: 0.5, angular_damping: 0.5, }) - .insert(ActiveEvents::COLLISION_EVENTS); + .insert(ActiveEvents::COLLISION_EVENTS) + .with_children(|c| { + c.spawn_bundle(TransformBundle::from_transform(Transform::from_xyz( + 0., -33., 0., + ))) + .insert(Sensor) + .insert(Collider::cuboid(30., 0.5)) + .insert(ActiveEvents::COLLISION_EVENTS) + .insert(CollisionCount(0)); + }); if is_player { entity_commands.insert(Player); @@ -214,67 +226,95 @@ fn collision_event_system( Option<&Player>, )>, pass_through_filter_query: Query<&PassThroughFilter>, + mut collision_counter_query: Query<&mut CollisionCount>, mut app_state: ResMut>, audio: Res>, ) { for collision_event in collision_events.iter() { - if let CollisionEvent::Started(e1, e2, flags) = collision_event { - 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)) - { - 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 - && 4. - new_color.length_squared() < 0.1 + 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)) { - app_state.replace(AppState::Win).ok(); + 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 + && 4. - new_color.length_squared() < 0.1 + { + app_state.replace(AppState::Win).ok(); + } + + // position character based on current player location + spawn_character( + &mut commands, + &character_meshes, + &mut materials, + &audio, + 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 *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)); - // position character based on current player location - spawn_character( - &mut commands, - &character_meshes, - &mut materials, - &audio, - 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(); + if c_player.is_some() { + audio + .send(AudioMsg::Color([ + c_color.0.r(), + c_color.0.g(), + c_color.0.b(), + ])) + .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; + } } - } 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(); + } + 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); } } } @@ -328,7 +368,8 @@ fn change_character_system( fn player_movement_system( keyboard_input: Res>, - mut characters: Query<&mut Velocity, With>, + mut characters: Query<(&mut Velocity, &Children), With>, + collision_counter_query: Query<&CollisionCount>, audio: Res>, ) { let right_pressed: bool = @@ -336,12 +377,14 @@ fn player_movement_system( let left_pressed: bool = keyboard_input.pressed(KeyCode::Left) || keyboard_input.pressed(KeyCode::A); - for mut velocity in characters.iter_mut() { + 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) { + if keyboard_input.just_pressed(KeyCode::Space) + && collision_counter_query.get(children[0]).unwrap().0 != 0 + { audio.send(AudioMsg::Jump).ok(); - velocity.linvel.y = 500.; + velocity.linvel.y = 700.; } } }