From 0ba313e98705dd2032547b3c3bc0510157f1bc87 Mon Sep 17 00:00:00 2001 From: Orlando Valverde Date: Sat, 23 Jul 2022 21:18:18 -0500 Subject: [PATCH] Add stopwatch feature --- src/core/save_file/mod.rs | 12 ++++---- src/core/save_file/stock.rs | 7 +---- src/resources/colors.rs | 6 ++++ src/resources/level/mod.rs | 30 ++++++++++++++----- src/resources/save_file/mod.rs | 18 +++++++----- src/scenes/level/mod.rs | 27 ++++++++++++----- src/scenes/level/ui.rs | 38 ++++++++++++++++-------- src/scenes/selection/ui.rs | 21 +++++++++---- src/scenes/title/ui.rs | 4 +-- src/scenes/win/mod.rs | 9 ++++-- src/scenes/win/ui.rs | 47 +++++++++++++++++++++++++----- src/ui/components/text/dynamic.rs | 10 +++---- src/ui/components/text/embossed.rs | 16 +++++----- src/ui/components/text/mod.rs | 8 +++++ src/ui/components/text/simple.rs | 6 ++-- 15 files changed, 179 insertions(+), 80 deletions(-) diff --git a/src/core/save_file/mod.rs b/src/core/save_file/mod.rs index fa482d9..7813aa7 100644 --- a/src/core/save_file/mod.rs +++ b/src/core/save_file/mod.rs @@ -22,22 +22,22 @@ pub fn save(save_file: &SaveFile) { } #[must_use] -pub fn get_record(save_file: &SaveFile, tag: &LevelTag) -> usize { +pub fn get_record(save_file: &SaveFile, tag: &LevelTag) -> (usize, f32) { match tag { LevelTag::Stock(index) => save_file.get_stock_level_record(index), } } -pub fn set_record(save_file: &mut SaveFile, tag: &LevelTag, moves: usize) { +pub fn set_record(save_file: &mut SaveFile, tag: &LevelTag, record: (usize, f32)) { match tag { - LevelTag::Stock(index) => save_file.set_stock_level_record(index, moves), + LevelTag::Stock(index) => save_file.set_stock_level_record(index, record), }; } -pub fn set_if_new_record(save_file: &mut SaveFile, tag: &LevelTag, moves: usize) { +pub fn set_if_new_record(save_file: &mut SaveFile, tag: &LevelTag, moves: usize, time: f32) { let record = get_record(save_file, tag); - if record == 0 || record > moves { - set_record(save_file, tag, moves); + if record.0 == 0 || record.0 > moves || record.1 > time { + set_record(save_file, tag, (moves, time)); } } diff --git a/src/core/save_file/stock.rs b/src/core/save_file/stock.rs index 034db79..4e7a01a 100644 --- a/src/core/save_file/stock.rs +++ b/src/core/save_file/stock.rs @@ -1,15 +1,10 @@ use crate::resources::{level::TOTAL_STOCK_LEVELS, prelude::*}; -#[must_use] -pub fn total(save_file: &SaveFile) -> usize { - save_file.stock.iter().sum() -} - pub fn unlock(save_file: &mut SaveFile, level: &Level) { let LevelTag::Stock(index) = level.tag; if save_file.stock_levels_len() == index + 1 && save_file.stock_levels_len() < TOTAL_STOCK_LEVELS { - save_file.insert_stock_level_record(0); + save_file.insert_stock_level_record((0, 0.0)); } } diff --git a/src/resources/colors.rs b/src/resources/colors.rs index 84f316d..8f99c25 100644 --- a/src/resources/colors.rs +++ b/src/resources/colors.rs @@ -27,6 +27,12 @@ impl Colors { blue: 91.0 / u8::MAX as f32, alpha: 1.0, }; + pub const SECONDARY_TRANSPARENT: Color = Color::Rgba { + red: 108.0 / u8::MAX as f32, + green: 255.0 / u8::MAX as f32, + blue: 91.0 / u8::MAX as f32, + alpha: 0.5, + }; pub const LIGHT: Color = Color::Rgba { red: 227.0 / u8::MAX as f32, green: 227.0 / u8::MAX as f32, diff --git a/src/resources/level/mod.rs b/src/resources/level/mod.rs index e0fd88b..ed8d98e 100644 --- a/src/resources/level/mod.rs +++ b/src/resources/level/mod.rs @@ -8,7 +8,7 @@ pub mod prelude; use std::time::Duration; -use bevy::core::Timer; +use bevy::core::{Stopwatch, Timer}; use map::{MAP_COLS, MAP_ROWS}; use prelude::*; use snapshots::{LevelSnapshots, MAX_SNAPSHOTS}; @@ -23,25 +23,26 @@ pub struct LevelDone { pub struct Level { pub tag: LevelTag, pub state: LevelState, - pub record: usize, + pub record: (usize, f32), pub snapshots: LevelSnapshots, pub undos: usize, pub moves: usize, pub timer: Timer, + pub stopwatch: Stopwatch, } impl Default for Level { fn default() -> Level { let state = LevelState::default(); let tag = LevelTag::Stock(0); - let record = 0; + let record = (0, 0.0); Level::new(tag, state, record) } } impl Level { #[must_use] - pub fn new(tag: LevelTag, state: LevelState, record: usize) -> Level { + pub fn new(tag: LevelTag, state: LevelState, record: (usize, f32)) -> Level { Level { tag, state, @@ -50,6 +51,7 @@ impl Level { undos: 4, moves: 0, timer: Timer::from_seconds(0.25, false), + stopwatch: Stopwatch::new(), } } @@ -131,12 +133,17 @@ impl Level { #[must_use] pub fn is_record_set(&self) -> bool { - self.record > 0 + self.record.0 > 0 } #[must_use] - pub fn is_new_record(&self) -> bool { - self.record == 0 || self.moves < self.record + pub fn new_record_moves(&self) -> bool { + self.record.0 == 0 || self.moves < self.record.0 + } + + #[must_use] + pub fn new_record_time(&self) -> bool { + self.record.1 == 0.0 || self.stopwatch.elapsed().as_secs_f32() < self.record.1 } #[must_use] @@ -175,6 +182,15 @@ impl Level { self.timer.tick(delta); } + pub fn tick_stopwatch(&mut self, delta: Duration) { + self.stopwatch.tick(delta); + } + + #[must_use] + pub fn stopwatch_elapsed(&self) -> Duration { + self.stopwatch.elapsed() + } + #[must_use] pub fn timer_finished(&self) -> bool { self.timer.finished() diff --git a/src/resources/save_file/mod.rs b/src/resources/save_file/mod.rs index 8043ca9..9c96828 100644 --- a/src/resources/save_file/mod.rs +++ b/src/resources/save_file/mod.rs @@ -8,18 +8,20 @@ pub use handle::SaveFileHandle; #[derive(TypeUuid, Serialize, Deserialize, Clone)] #[uuid = "2e5bbfc2-8dfd-4547-8c85-cbaf27533998"] pub struct SaveFile { - pub stock: Vec, + pub stock: Vec<(usize, f32)>, } impl Default for SaveFile { fn default() -> SaveFile { - SaveFile { stock: vec![0] } + SaveFile { + stock: vec![(0, 0.0)], + } } } impl SaveFile { #[must_use] - pub fn new(stock: Vec) -> SaveFile { + pub fn new(stock: Vec<(usize, f32)>) -> SaveFile { SaveFile { stock } } @@ -28,16 +30,16 @@ impl SaveFile { self.stock.len() } - pub fn insert_stock_level_record(&mut self, moves: usize) { - self.stock.push(moves); + pub fn insert_stock_level_record(&mut self, record: (usize, f32)) { + self.stock.push(record); } - pub fn set_stock_level_record(&mut self, index: &usize, moves: usize) { - self.stock[*index] = moves; + pub fn set_stock_level_record(&mut self, index: &usize, record: (usize, f32)) { + self.stock[*index] = record; } #[must_use] - pub fn get_stock_level_record(&self, index: &usize) -> usize { + pub fn get_stock_level_record(&self, index: &usize) -> (usize, f32) { self.stock[*index] } } diff --git a/src/scenes/level/mod.rs b/src/scenes/level/mod.rs index 4737e1e..0cfbbef 100644 --- a/src/scenes/level/mod.rs +++ b/src/scenes/level/mod.rs @@ -38,8 +38,8 @@ impl Plugin for LevelPlugin { .with_system(update_player_position) .with_system(update_counters) .with_system(update_map) - .with_system(check_level_state) - .with_system(lever_timer_finished), + .with_system(update_level_state) + .with_system(check_lever_timer_finished), ) .add_system_set( SystemSet::on_exit(GameState::Level) @@ -178,11 +178,20 @@ fn update_counters( mut texts: Query<(&mut Text, &TextMarker), With>, ) { for (mut text, counter) in texts.iter_mut() { - let value = match counter.kind { - TextKind::Moves => level.moves, - TextKind::Undos => level.undos, + match counter.kind { + TextKind::Moves => core::ui::update_dynamic_text(&mut text, level.moves.to_string()), + TextKind::Undos => core::ui::update_dynamic_text(&mut text, level.undos.to_string()), + TextKind::Stopwatch => { + let duration = level.stopwatch_elapsed(); + let milliseconds = duration.subsec_millis(); + let seconds = duration.as_secs() % 60; + let minutes = (duration.as_secs() / 60) % 60; + core::ui::update_dynamic_text( + &mut text, + format!("{:02}:{:02}:{:03}", minutes, seconds, milliseconds), + ); + } }; - core::ui::update_dynamic_text(&mut text, value.to_string()); } } @@ -204,13 +213,15 @@ fn update_map( } } -fn check_level_state(time: Res