Skip to content

Commit

Permalink
Deal with game over state changes in a uniform way.
Browse files Browse the repository at this point in the history
  • Loading branch information
cryscan committed Nov 16, 2022
1 parent 606b9b1 commit a8b8859
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 23 deletions.
1 change: 1 addition & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,5 +104,6 @@ pub const HEALTH_BAR_DAMP: f32 = 1.0;
pub const TIME_SCALE_DAMP: f32 = 100.0;
pub const GAME_OVER_TIME_SCALE_DAMP: f32 = 5.0;

pub const GAME_OVER_SLOW_MOTION_TIME_SCALE: f32 = 0.2;
pub const GAME_OVER_SLOW_MOTION_DURATION: f32 = 0.8;
pub const GAME_OVER_STATE_CHANGE_DURATION: f32 = 2.0;
17 changes: 1 addition & 16 deletions src/game/battle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,34 +60,20 @@ fn enter_battle(
}

/// Deals with [`GameOverEvent`].
/// The system triggers a slow motion with the duration of [`GAME_OVER_SLOW_MOTION_DURATION`]
/// and also changes the [`AppState`] after [`GAME_OVER_STATE_CHANGE_DURATION`].
/// Changes the [`AppState`] after [`GAME_OVER_STATE_CHANGE_DURATION`].
fn game_over_system(
time: Res<Time>,
mut time_scale: ResMut<TimeScale>,
mut app_state: ResMut<State<AppState>>,
mut game_over_events: EventReader<GameOverEvent>,
mut game_over: Local<GameOver>,
) {
if let Some(event) = game_over.event {
let mut target_time_scale = 0.2;
let mut time_scale_damp = TIME_SCALE_DAMP;

if game_over.slow_motion_timer.tick(time.delta()).finished() {
target_time_scale = 1.0;
time_scale_damp = GAME_OVER_TIME_SCALE_DAMP;
}
time_scale.0 = time_scale
.0
.damp(target_time_scale, time_scale_damp, time.delta_seconds());

// it's time to switch state
if game_over
.state_change_timer
.tick(time.delta())
.just_finished()
{
time_scale.reset();
*game_over = GameOver::default();

match event {
Expand All @@ -98,7 +84,6 @@ fn game_over_system(
} else {
for event in game_over_events.iter() {
game_over.event = Some(*event);
time_scale.0 = 0.2;
}
}
}
42 changes: 42 additions & 0 deletions src/game/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ impl Plugin for GamePlugin {
.with_system(move_slit_block)
.with_system(slits_system)
// effects and juice
.with_system(game_over_slow_motion)
.with_system(bounce_audio)
.with_system(score_audio)
.with_system(score_effects)
Expand Down Expand Up @@ -524,12 +525,17 @@ fn reset_ball(
mut commands: Commands,
mut player_miss_events: EventReader<PlayerMissEvent>,
mut player_hit_events: EventReader<PlayerHitEvent>,
mut time_scale: ResMut<TimeScale>,
mut query: Query<(Entity, &mut Transform), (With<Ball>, With<Motion>)>,
) {
let mut closure = |ball| -> Option<()> {
let (_, mut transform) = query.get_mut(ball).ok()?;
transform.translation = Vec3::new(0.0, 0.0, -1.0);
commands.entity(ball).remove::<Motion>();

// also reset time scale
time_scale.reset();

Some(())
};

Expand Down Expand Up @@ -716,6 +722,42 @@ fn player_miss(
}
}

/// Deals with [`GameOverEvent`].
/// The system triggers a slow motion with the duration of [`GAME_OVER_SLOW_MOTION_DURATION`]
fn game_over_slow_motion(
time: Res<Time>,
mut time_scale: ResMut<TimeScale>,
mut game_over_events: EventReader<GameOverEvent>,
mut game_over: Local<GameOver>,
) {
if game_over.event.is_some() {
let mut target_time_scale = GAME_OVER_SLOW_MOTION_TIME_SCALE;
let mut time_scale_damp = TIME_SCALE_DAMP;

if game_over.slow_motion_timer.tick(time.delta()).finished() {
target_time_scale = 1.0;
time_scale_damp = GAME_OVER_TIME_SCALE_DAMP;
}

time_scale.0 = time_scale
.0
.damp(target_time_scale, time_scale_damp, time.delta_seconds());

if game_over
.state_change_timer
.tick(time.delta())
.just_finished()
{
time_scale.reset();
*game_over = GameOver::default();
}
} else {
for event in game_over_events.iter() {
game_over.event = Some(*event);
}
}
}

/// Emits [`BounceEvent`] when there the ball hits something after debouncing.
#[allow(clippy::too_many_arguments)]
fn ball_bounce(
Expand Down
43 changes: 36 additions & 7 deletions src/game/practice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,28 @@ fn enter_practice(

/// Triggers a full recovery of enemy base health after beating it.
fn recover_enemy_health(
time: Res<Time>,
mut game_over_events: EventReader<GameOverEvent>,
mut game_over: Local<GameOver>,
mut heal_events: EventWriter<HealEvent>,
) {
for event in game_over_events.iter() {
match event {
GameOverEvent::Win => heal_events.send(HealEvent(Heal::default())),
GameOverEvent::Lose => {}
if let Some(event) = game_over.event {
// it's time to switch state
if game_over
.state_change_timer
.tick(time.delta())
.just_finished()
{
*game_over = GameOver::default();

match event {
GameOverEvent::Win => heal_events.send(HealEvent(Heal::default())),
GameOverEvent::Lose => {}
}
}
} else {
for event in game_over_events.iter() {
game_over.event = Some(*event);
}
}
}
Expand All @@ -87,11 +102,25 @@ fn player_ball_infinite(mut query: Query<&mut PlayerBase>) {
}

fn progress_system(
time: Res<Time>,
mut practice_state: ResMut<State<PracticeState>>,
game_over_events: EventReader<GameOverEvent>,
mut game_over_events: EventReader<GameOverEvent>,
mut game_over: Local<GameOver>,
) {
if !game_over_events.is_empty() {
let _ = practice_state.set(PracticeState::Slits);
if game_over.event.is_some() {
// it's time to switch state
if game_over
.state_change_timer
.tick(time.delta())
.just_finished()
{
*game_over = GameOver::default();
let _ = practice_state.set(PracticeState::Slits);
}
} else {
for event in game_over_events.iter() {
game_over.event = Some(*event);
}
}
}

Expand Down

0 comments on commit a8b8859

Please sign in to comment.