diff --git a/src/bin/flappy/main.rs b/src/bin/flappy/main.rs index 1f37e4b..9912375 100644 --- a/src/bin/flappy/main.rs +++ b/src/bin/flappy/main.rs @@ -12,7 +12,9 @@ fn main() { .init_state::() .add_systems(Startup, (init_bird, init_obstacles, init_ui, tweak_camera.after(setup_camera))) .add_systems(OnEnter(PlayerState::Alive), alive_bird) - .add_systems(OnExit(PlayerState::Alive), kill_bird) + .add_systems(OnEnter(PlayerState::Pause), pause_bird) + .add_systems(OnEnter(PlayerState::Stasis), pause_bird) + .add_systems(OnEnter(PlayerState::Rewind), pause_bird) .add_systems( Update, ( @@ -42,6 +44,8 @@ fn main() { rewind.run_if(in_state(PlayerState::Rewind)), // Camera follows when bird moves regardless of player state camera_follow_bird.run_if(any_component_changed::), + // Pause when the player presses Escape + pause_game.run_if(input_just_pressed(KeyCode::Escape)), ), ) .run(); @@ -63,10 +67,11 @@ struct Bird; #[derive(States, Clone, Eq, PartialEq, Debug, Hash, Default, Component)] enum PlayerState { - #[default] Alive, Rewind, - Dead, + Stasis, + #[default] + Pause } // A tape tracking the bird's state every frame @@ -96,7 +101,7 @@ fn init_bird( let t = Transform::from_xyz(0.0, 0.0, 0.0).with_rotation(Quat::from_rotation_x(PI / 2.0)); let physics = ( - RigidBody::Dynamic, + RigidBody::Static, Collider::capsule(1.0, 1.0), Mass(1.0), ExternalForce::new(Vec3::X * 1.0).with_persistence(true), ExternalImpulse::default().with_persistence(false), @@ -150,7 +155,7 @@ fn init_obstacles( // screens and then "move" them around. // This is considerably more complexity so can be implemented later, but would keep memory // overhead fairly static. - (1..50).for_each(|i| { + (1..99).for_each(|i| { // TODO: Jitter up/down/close/far of pipes for challenge let above = Transform::from_xyz(5.0 * i as f32, 4.0, 0.0); let below = Transform::from_xyz(5.0 * i as f32, -4.0, 0.0); @@ -173,12 +178,38 @@ fn init_ui( flex_direction: FlexDirection::Column, ..default() }, - PlayerState::Dead, + PlayerState::Stasis, children![ Text::new("You Died"), Text::new("Press R to Rewind"), ], )); + + fn start_game(_trigger: Trigger>, mut next: ResMut>) { + next.set(PlayerState::Alive); + } + + commands.spawn(( + Node { + align_self: AlignSelf::Center, + justify_self: JustifySelf::Center, + flex_direction: FlexDirection::Column, + ..default() + }, + Button, + // TODO: Add Pause (basically Stasis) state + PlayerState::Pause, + children![ + Text::new("Go!"), + ], + )).observe(start_game); +} + +/// Pause the game when the player presses "Escape" +fn pause_game( + mut next: ResMut>, +) { + next.set(PlayerState::Pause); } // TODO: Create floor (and ceiling?) @@ -268,7 +299,7 @@ fn detect_dead( if obstacles.iter().any(|obstacle| { bird.intersects(obstacle) }) { - next.set(PlayerState::Dead); + next.set(PlayerState::Stasis); } } @@ -276,17 +307,17 @@ fn alive_bird( #[cfg(debug_assertions)] state: Res>, mut bird: Single<&mut RigidBody, With>, ) { - debug_assert!(!matches!(state.get(), PlayerState::Dead)); - debug!("Aliving bird"); + debug_assert!(matches!(state.get(), PlayerState::Alive)); + debug!("Setting bird to Dynamic"); **bird = RigidBody::Dynamic; } -fn kill_bird( +fn pause_bird( #[cfg(debug_assertions)] state: Res>, mut bird: Single<&mut RigidBody, With>, ) { debug_assert!(!matches!(state.get(), PlayerState::Alive)); - debug!("Killing bird"); + debug!("Setting bird to Static"); **bird = RigidBody::Static; }