|
|
|
|
@ -17,6 +17,7 @@ fn main() {
|
|
|
|
|
.init_resource::<Score>()
|
|
|
|
|
.init_resource::<RewindFrames>()
|
|
|
|
|
.init_resource::<Flaps>()
|
|
|
|
|
.init_resource::<Deaths>()
|
|
|
|
|
.init_state::<PlayerState>()
|
|
|
|
|
.add_systems(
|
|
|
|
|
Startup,
|
|
|
|
|
@ -52,7 +53,7 @@ fn main() {
|
|
|
|
|
// Systems to run in the "play" state
|
|
|
|
|
(
|
|
|
|
|
// Only flap when we press the space key
|
|
|
|
|
flap.run_if(input_just_pressed(KeyCode::Space)),
|
|
|
|
|
flap_kb.run_if(input_just_pressed(KeyCode::Space)),
|
|
|
|
|
// Rewinding systems
|
|
|
|
|
record.run_if(any_component_changed::<Transform>),
|
|
|
|
|
)
|
|
|
|
|
@ -71,11 +72,13 @@ fn main() {
|
|
|
|
|
(
|
|
|
|
|
sync_resource_to_ui::<Score>.run_if(resource_changed::<Score>),
|
|
|
|
|
sync_resource_to_ui::<Flaps>.run_if(resource_changed::<Flaps>),
|
|
|
|
|
sync_resource_to_ui::<Deaths>.run_if(resource_changed::<Deaths>),
|
|
|
|
|
sync_resource_to_ui::<RewindFrames>.run_if(resource_changed::<RewindFrames>),
|
|
|
|
|
),
|
|
|
|
|
scoring.run_if(on_event::<CollisionEnded>)
|
|
|
|
|
),
|
|
|
|
|
)
|
|
|
|
|
.add_observer(flap)
|
|
|
|
|
.run();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -238,6 +241,7 @@ fn init_ui(mut commands: Commands) {
|
|
|
|
|
(SyncResource::<Score>::default(), Text::default(), TextLayout::new_with_justify(JustifyText::Center)),
|
|
|
|
|
(SyncResource::<Flaps>::default(), Text::default(), TextLayout::new_with_justify(JustifyText::Center)),
|
|
|
|
|
(SyncResource::<RewindFrames>::default(), Text::default(), TextLayout::new_with_justify(JustifyText::Center)),
|
|
|
|
|
(SyncResource::<Deaths>::default(), Text::default(), TextLayout::new_with_justify(JustifyText::Center)),
|
|
|
|
|
(Text::new("Press R to Rewind"), TextLayout::new_with_justify(JustifyText::Center)),
|
|
|
|
|
],
|
|
|
|
|
));
|
|
|
|
|
@ -261,27 +265,50 @@ fn init_ui(mut commands: Commands) {
|
|
|
|
|
))
|
|
|
|
|
.observe(start_game);
|
|
|
|
|
|
|
|
|
|
fn start_rewind(trigger: Trigger<Pointer<Pressed>>, mut next: ResMut<NextState<PlayerState>>) {
|
|
|
|
|
next.set(PlayerState::Rewind);
|
|
|
|
|
}
|
|
|
|
|
commands.spawn(
|
|
|
|
|
Node {
|
|
|
|
|
align_self: AlignSelf::End,
|
|
|
|
|
justify_self: JustifySelf::Center,
|
|
|
|
|
flex_direction: FlexDirection::Row,
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
).with_children(|parent| {
|
|
|
|
|
|
|
|
|
|
parent
|
|
|
|
|
.spawn((
|
|
|
|
|
Node {
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
Button,
|
|
|
|
|
children![Text::new("Rewind!"),],
|
|
|
|
|
))
|
|
|
|
|
.observe(start_rewind)
|
|
|
|
|
.observe(end_rewind);
|
|
|
|
|
|
|
|
|
|
parent
|
|
|
|
|
.spawn((
|
|
|
|
|
Node {
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
Button,
|
|
|
|
|
children![Text::new("Flap!"),],
|
|
|
|
|
))
|
|
|
|
|
.observe(flap_button);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn end_rewind(trigger: Trigger<Pointer<Released>>, mut next: ResMut<NextState<PlayerState>>) {
|
|
|
|
|
next.set(PlayerState::Alive);
|
|
|
|
|
}
|
|
|
|
|
fn start_rewind(_trigger: Trigger<Pointer<Pressed>>, mut next: ResMut<NextState<PlayerState>>) {
|
|
|
|
|
next.set(PlayerState::Rewind);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
commands
|
|
|
|
|
.spawn((
|
|
|
|
|
Node {
|
|
|
|
|
align_self: AlignSelf::End,
|
|
|
|
|
justify_self: JustifySelf::Center,
|
|
|
|
|
flex_direction: FlexDirection::Column,
|
|
|
|
|
..default()
|
|
|
|
|
},
|
|
|
|
|
Button,
|
|
|
|
|
children![Text::new("Rewind!"),],
|
|
|
|
|
))
|
|
|
|
|
.observe(start_rewind)
|
|
|
|
|
.observe(end_rewind);
|
|
|
|
|
fn end_rewind(_trigger: Trigger<Pointer<Released>>, mut next: ResMut<NextState<PlayerState>>) {
|
|
|
|
|
next.set(PlayerState::Alive);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn flap_button(trigger: Trigger<Pointer<Pressed>>, mut commands: Commands, bird: Single<Entity, With<Bird>>) {
|
|
|
|
|
let e = *bird;
|
|
|
|
|
info!("Flapping {:?}", e);
|
|
|
|
|
commands.trigger_targets(Flap, e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Pause the game when the player presses "Escape"
|
|
|
|
|
@ -296,12 +323,29 @@ fn un_pause_game(mut next: ResMut<NextState<PlayerState>>) {
|
|
|
|
|
// TODO: Create floor (and ceiling?)
|
|
|
|
|
// Q: Move bird + camera or move world around bird & camera?
|
|
|
|
|
// TODO: Obstacles
|
|
|
|
|
#[derive(Component, Clone, Event)]
|
|
|
|
|
struct Flap;
|
|
|
|
|
|
|
|
|
|
fn flap(
|
|
|
|
|
// Observer for flapping
|
|
|
|
|
fn flap(trigger: Trigger<Flap>,
|
|
|
|
|
mut bird: Query<&mut ExternalImpulse, With<Bird>>,
|
|
|
|
|
mut flaps: ResMut<Flaps>,
|
|
|
|
|
) {
|
|
|
|
|
info!("real flap for {:?}", trigger.target());
|
|
|
|
|
// Increment flap stat
|
|
|
|
|
flaps.0 += 1;
|
|
|
|
|
|
|
|
|
|
// Flap birds wings
|
|
|
|
|
if let Ok(mut f) = bird.get_mut(trigger.target()) {
|
|
|
|
|
f.apply_impulse(Vec2::Y * 5000.0 + Vec2::X * 1000.0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn flap_kb(
|
|
|
|
|
#[cfg(debug_assertions)] state: Res<State<PlayerState>>,
|
|
|
|
|
#[cfg(debug_assertions)] keycode: Res<ButtonInput<KeyCode>>,
|
|
|
|
|
mut bird: Query<(&Transform, &mut ExternalImpulse), With<Bird>>,
|
|
|
|
|
mut flaps: ResMut<Flaps>,
|
|
|
|
|
birds: Query<Entity, With<Bird>>,
|
|
|
|
|
mut commands: Commands,
|
|
|
|
|
) {
|
|
|
|
|
debug_assert!(
|
|
|
|
|
matches!(state.get(), PlayerState::Alive),
|
|
|
|
|
@ -312,12 +356,9 @@ fn flap(
|
|
|
|
|
"Only flap when space is just pressed"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Increment flap stat
|
|
|
|
|
flaps.0 += 1;
|
|
|
|
|
|
|
|
|
|
// Flap birds wings
|
|
|
|
|
bird.iter_mut().for_each(|(_, mut f)| {
|
|
|
|
|
f.apply_impulse(Vec2::Y * 5000.0 + Vec2::X * 1000.0);
|
|
|
|
|
birds.iter().for_each(|e| {
|
|
|
|
|
info!("Flapping {:?}", e);
|
|
|
|
|
commands.trigger_targets(Flap, e);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -410,10 +451,18 @@ fn alive_bird(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn pause_bird(
|
|
|
|
|
#[cfg(debug_assertions)] state: Res<State<PlayerState>>,
|
|
|
|
|
state: Res<State<PlayerState>>,
|
|
|
|
|
mut bird: Single<&mut RigidBody, With<Bird>>,
|
|
|
|
|
mut deaths: ResMut<Deaths>,
|
|
|
|
|
) {
|
|
|
|
|
debug_assert!(!matches!(state.get(), PlayerState::Alive));
|
|
|
|
|
|
|
|
|
|
// Increment death count
|
|
|
|
|
match state.get() {
|
|
|
|
|
PlayerState::Stasis => deaths.0 += 1,
|
|
|
|
|
_ => (),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
debug!("Setting bird to Static");
|
|
|
|
|
**bird = RigidBody::Static;
|
|
|
|
|
}
|
|
|
|
|
@ -455,6 +504,16 @@ impl Display for Flaps {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Track number of times player died
|
|
|
|
|
#[derive(Resource, Default)]
|
|
|
|
|
struct Deaths(usize);
|
|
|
|
|
|
|
|
|
|
impl Display for Deaths {
|
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
|
|
|
writeln!(f, "Deaths: {}", self.0)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn scoring(
|
|
|
|
|
mut events: EventReader<CollisionEnded>,
|
|
|
|
|
state: Res<State<PlayerState>>,
|
|
|
|
|
|