Skip to content

Commit

Permalink
Add stopwatch feature
Browse files Browse the repository at this point in the history
  • Loading branch information
septum committed Jul 24, 2022
1 parent 930e738 commit 0ba313e
Show file tree
Hide file tree
Showing 15 changed files with 179 additions and 80 deletions.
12 changes: 6 additions & 6 deletions src/core/save_file/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
}

Expand Down
7 changes: 1 addition & 6 deletions src/core/save_file/stock.rs
Original file line number Diff line number Diff line change
@@ -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));
}
}
6 changes: 6 additions & 0 deletions src/resources/colors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
30 changes: 23 additions & 7 deletions src/resources/level/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -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,
Expand All @@ -50,6 +51,7 @@ impl Level {
undos: 4,
moves: 0,
timer: Timer::from_seconds(0.25, false),
stopwatch: Stopwatch::new(),
}
}

Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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()
Expand Down
18 changes: 10 additions & 8 deletions src/resources/save_file/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<usize>,
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<usize>) -> SaveFile {
pub fn new(stock: Vec<(usize, f32)>) -> SaveFile {
SaveFile { stock }
}

Expand All @@ -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]
}
}
27 changes: 19 additions & 8 deletions src/scenes/level/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -178,11 +178,20 @@ fn update_counters(
mut texts: Query<(&mut Text, &TextMarker), With<TextMarker>>,
) {
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());
}
}

Expand All @@ -204,13 +213,15 @@ fn update_map(
}
}

fn check_level_state(time: Res<Time>, mut level: ResMut<Level>) {
fn update_level_state(time: Res<Time>, mut level: ResMut<Level>) {
if level.no_remaining_zones() {
level.tick_timer(time.delta());
} else {
level.tick_stopwatch(time.delta());
}
}

fn lever_timer_finished(level: Res<Level>, mut game_state: ResMut<State<GameState>>) {
fn check_lever_timer_finished(level: Res<Level>, mut game_state: ResMut<State<GameState>>) {
if level.timer_finished() {
game_state.set(GameState::Win).unwrap();
}
Expand Down
38 changes: 26 additions & 12 deletions src/scenes/level/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,22 @@ fn spawn_ui_camera(commands: &mut Commands) {
pub fn spawn_ui(commands: &mut Commands, level: &Level, fonts: &Fonts) {
let font = &fonts.upheavtt;
let record_new_level = if level.is_record_set() {
format!("Record: {}", level.record)
format!("Record: {}", level.record.0)
} else {
"New Level!".to_string()
};

let mut overlay = Overlay::new();
let mut top = Housing::percent(98.0, 7.0);
let mut bottom = Housing::percent(98.0, 8.0);
let mut top = Housing::percent(97.0, 7.0);
let mut bottom = Housing::percent(97.0, 7.0);

let mut top_left = Housing::percent(50.0, 100.0);
let mut top_right = Housing::percent(50.0, 100.0);
let bottom_left = Housing::percent(50.0, 100.0);
let bottom_right = Housing::percent(50.0, 100.0);

let mut level_housing = Housing::percent(100.0, 100.0);
let mut stopwatch_housing = Housing::percent(100.0, 50.0);
let mut moves_housing = Housing::percent(100.0, 50.0);
let mut record_housing = Housing::percent(100.0, 50.0);
let mut reload_housing = Housing::percent(100.0, 50.0);
Expand All @@ -39,25 +41,32 @@ pub fn spawn_ui(commands: &mut Commands, level: &Level, fonts: &Fonts) {
let mut undo_housing = Housing::percent(100.0, 50.0);

let mut level_name = EmbossedText::medium(format!("Level {}", level.get_name()), font);
let mut moves = DynamicText::small("Moves: ", font);
let mut stopwatch = DynamicText::small("", font);
let mut record_new_level = EmbossedText::small(record_new_level, font);
let mut undos_left = DynamicText::small("Undos: ", font);
let moves = DynamicText::medium("Moves: ", font);
let undos_left = DynamicText::medium("Undos: ", font);
let undo = EmbossedText::small("(B) - Undo Movement", font);
let reload = EmbossedText::small("(X) - Reload Level", font);
let selection = EmbossedText::small("(L3) - Level Selection", font);

moves.size(35.0);
undos_left.size(35.0);

level_name.foreground_color(Colors::LIGHT);
level_name.foreground_color(Colors::LIGHT).size(54.0);
record_new_level.foreground_color(Colors::SECONDARY);
stopwatch.color(Colors::SECONDARY);

overlay.justify_content(JustifyContent::SpaceBetween);
top.flex_direction(FlexDirection::Row);
bottom.flex_direction(FlexDirection::Row);

top_left.align_items(AlignItems::FlexStart);
top_right.align_items(AlignItems::FlexEnd);
level_housing
.align_items(AlignItems::FlexStart)
.position_type(PositionType::Absolute)
.top(-6.0);
stopwatch_housing
.align_items(AlignItems::FlexStart)
.position_type(PositionType::Absolute)
.top(44.0);
moves_housing.align_items(AlignItems::FlexEnd);
record_housing
.align_items(AlignItems::FlexEnd)
Expand All @@ -67,20 +76,25 @@ pub fn spawn_ui(commands: &mut Commands, level: &Level, fonts: &Fonts) {
reload_housing
.align_items(AlignItems::FlexStart)
.position_type(PositionType::Absolute)
.top(-4.0);
.top(-2.0);
selection_housing.align_items(AlignItems::FlexStart);
undos_left_housing
.align_items(AlignItems::FlexEnd)
.position_type(PositionType::Absolute)
.top(-4.0);
.top(-8.0);
undo_housing.align_items(AlignItems::FlexEnd);

overlay.spawn(
commands,
|parent| {
top.spawn(parent, |parent| {
top_left.spawn(parent, |parent| {
level_name.spawn(parent);
level_housing.spawn(parent, |parent| {
level_name.spawn(parent);
});
stopwatch_housing.spawn(parent, |parent| {
stopwatch.spawn(parent, TextMarker::stopwatch());
});
});
top_right.spawn(parent, |parent| {
moves_housing.spawn(parent, |parent| {
Expand Down
21 changes: 16 additions & 5 deletions src/scenes/selection/ui.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::time::Duration;

use bevy::prelude::*;

use crate::{
Expand All @@ -17,14 +19,23 @@ fn spawn_ui_camera(commands: &mut Commands) {
fn spawn_stock_buttons(parent: &mut ChildBuilder, save_file: &SaveFile, font: &Handle<Font>) {
let last_index = save_file.stock_levels_len();
for (index, record) in save_file.stock.iter().enumerate() {
let (text, color) = if record.0 > 0 {
let duration = Duration::from_secs_f32(record.1);
let milliseconds = duration.subsec_millis();
let seconds = duration.as_secs() % 60;
let minutes = (duration.as_secs() / 60) % 60;
let time = format!("{:02}:{:02}:{:03}", minutes, seconds, milliseconds);
(
format!("Record: {}\nTime: {}", record.0, time),
Colors::LIGHT,
)
} else {
("New Level!\n ".to_string(), Colors::SECONDARY)
};

let housing = Housing::percent(25.0, 25.0);
let button = ActionButton::square(format!("{}", index + 1), font);
let marker = ButtonMarker::stock_level(index, last_index == index + 1);
let (text, color) = if *record > 0 {
(format!("Record: {}", record), Colors::LIGHT)
} else {
("New Level!".to_string(), Colors::SECONDARY)
};
let mut record_new_level = SimpleText::small(text, font);

record_new_level.color(color);
Expand Down
4 changes: 1 addition & 3 deletions src/scenes/title/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,12 @@ pub fn spawn_ui(commands: &mut Commands, fonts: &Fonts) {
let mut actions = Housing::percent(100.0, 60.0);
let footer = Housing::percent(100.0, 30.0);

let mut title = EmbossedText::big("Pushin'\nBoxes", font);
let title = EmbossedText::big("Pushin'\nBoxes", font);
let notice = SimpleText::small("By @septum (gh)\nand @andresweyman (ig)", font);
let play = ActionButton::new("Play", font, button_size);
let instructions = ActionButton::new("Instructions", font, button_size);
let quit = ActionButton::new("Quit", font, button_size);

title.size(112.0);

overlay.justify_content(JustifyContent::SpaceEvenly);
bottom.justify_content(JustifyContent::SpaceBetween);
actions
Expand Down
Loading

0 comments on commit 0ba313e

Please sign in to comment.