Skip to content

Commit

Permalink
Add limit scene
Browse files Browse the repository at this point in the history
  • Loading branch information
septum committed Dec 22, 2022
1 parent 47b02d5 commit 19b6905
Show file tree
Hide file tree
Showing 15 changed files with 170 additions and 17 deletions.
Binary file modified assets/images/instructions.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions src/resources/input/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub enum ActionInput {
Reload,
Select,
Toggle,
Delete,
Exit,
}

Expand Down Expand Up @@ -35,6 +36,12 @@ impl ActionInputEvent {
}
}

pub fn delete() -> ActionInputEvent {
ActionInputEvent {
value: ActionInput::Delete,
}
}

pub fn exit() -> ActionInputEvent {
ActionInputEvent {
value: ActionInput::Exit,
Expand Down
1 change: 1 addition & 0 deletions src/resources/input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ fn gather_input(
KeyCode::Escape => action_event_writer.send(ActionInputEvent::exit()),
KeyCode::Space => action_event_writer.send(ActionInputEvent::select()),
KeyCode::Return => action_event_writer.send(ActionInputEvent::toggle()),
KeyCode::Delete => action_event_writer.send(ActionInputEvent::delete()),
_ => (),
};
}
Expand Down
5 changes: 3 additions & 2 deletions src/resources/level/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub mod prelude {
pub use super::map::{MapEntity, MapPosition};
pub use super::record::LevelRecord;
pub use super::state::LevelState;
pub use super::{Level, TOTAL_STOCK_LEVELS};
pub use super::{Level, TOTAL_CUSTOM_LEVELS, TOTAL_STOCK_LEVELS};
}

use std::time::Duration;
Expand All @@ -34,6 +34,7 @@ use self::{
use super::prelude::*;

pub const TOTAL_STOCK_LEVELS: usize = 16;
pub const TOTAL_CUSTOM_LEVELS: usize = 16;

pub struct Plugin;

Expand All @@ -48,7 +49,7 @@ pub fn insert_custom_level_handles(
mut level_handles: ResMut<LevelHandles>,
asset_server: Res<AssetServer>,
) {
for (_, (key, _)) in save_file.enumerated_custom_records() {
for (_, (key, _)) in save_file.ordered_custom_records() {
let split_key: Vec<&str> = key.split('$').collect();
let uuid = Uuid::parse_str(split_key[1]).expect("Cannot parse uuid");
let path = format!("levels/custom/{}.lvl", &split_key[1]);
Expand Down
20 changes: 15 additions & 5 deletions src/resources/save_file/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
mod handle;

use std::{env, fs::File, io::Write, iter::Enumerate, path::PathBuf, slice::Iter};
use std::{env, fs::File, io::Write, iter::Enumerate, path::PathBuf, slice::Iter, vec::IntoIter};

use bevy::{asset::LoadState, prelude::*, reflect::TypeUuid};
use hashbrown::{hash_map, HashMap};
use hashbrown::HashMap;
use ron::ser as serialize_ron;
use serde::{Deserialize, Serialize};

Expand Down Expand Up @@ -95,6 +95,10 @@ impl SaveFile {
self.custom_records.insert(key, level_record);
}

pub fn delete_custom_level_record(&mut self, key: &str) {
self.custom_records.remove(key);
}

pub fn unlock_new_level(&mut self, level: &Level) {
if let LevelKind::Stock(index) = level.kind {
let unlocked_levels = self.unlocked_levels();
Expand All @@ -116,15 +120,21 @@ impl SaveFile {
self.stock_records.len()
}

pub fn total_custom_levels(&self) -> usize {
pub fn number_custom_levels(&self) -> usize {
self.custom_records.len()
}

pub fn enumerated_stock_records(&self) -> Enumerate<Iter<LevelRecord>> {
self.stock_records.iter().enumerate()
}

pub fn enumerated_custom_records(&self) -> Enumerate<hash_map::Iter<String, LevelRecord>> {
self.custom_records.iter().enumerate()
pub fn ordered_custom_records(&self) -> Enumerate<IntoIter<(&String, &LevelRecord)>> {
let mut x = self
.custom_records
.iter()
.collect::<Vec<(&String, &LevelRecord)>>();
x.sort_by(|(a_key, _), (b_key, _)| a_key.cmp(b_key));

x.into_iter().enumerate()
}
}
6 changes: 6 additions & 0 deletions src/resources/scene.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ impl SceneTransitionEvent {
}
}

pub fn limit() -> Self {
Self {
state: GameState::Limit,
}
}

pub fn options() -> Self {
Self {
state: GameState::Options,
Expand Down
4 changes: 3 additions & 1 deletion src/resources/sounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,9 @@ fn play_music(
music
.play(match game_state.0 {
GameState::Title | GameState::Instructions => sounds.music_title.clone(),
GameState::Selection { .. } | GameState::Options => sounds.music_selection.clone(),
GameState::Selection { .. } | GameState::Options | GameState::Limit => {
sounds.music_selection.clone()
}
GameState::Level | GameState::Editor => sounds.music_level.clone(),
GameState::Win | GameState::Passed => sounds.music_win.clone(),
GameState::Loading => return,
Expand Down
2 changes: 2 additions & 0 deletions src/resources/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ impl SelectionKind {
}
}

#[must_use]
pub fn toggle(&self) -> Self {
match self {
Self::Stock => Self::Custom,
Expand All @@ -35,6 +36,7 @@ pub enum GameState {
Title,
Instructions,
Editor,
Limit,
Passed,
Options,
Selection { kind: SelectionKind },
Expand Down
10 changes: 10 additions & 0 deletions src/scenes/editor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ impl BevyPlugin for Plugin {
.add_enter_system_set(
GameState::Editor,
SystemSet::new()
.with_system(check_total_custom_levels)
.with_system(self::ui::spawn)
.with_system(Brush::insert)
.with_system(setup_level),
Expand Down Expand Up @@ -49,6 +50,15 @@ impl BevyPlugin for Plugin {
}
}

fn check_total_custom_levels(
save_file: Res<SaveFile>,
mut scene_transition_event_writer: EventWriter<SceneTransitionEvent>,
) {
if save_file.number_custom_levels() == TOTAL_CUSTOM_LEVELS {
scene_transition_event_writer.send(SceneTransitionEvent::limit());
}
}

fn setup_level(
mut commands: Commands,
images: Res<Images>,
Expand Down
46 changes: 46 additions & 0 deletions src/scenes/limit/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
mod ui;

use bevy::{app::Plugin as BevyPlugin, prelude::*};
use bevy_kira_audio::{AudioChannel, AudioControl};
use iyes_loopless::prelude::*;

use crate::{resources::prelude::*, ui::OverlayMarker};

pub struct Plugin;

impl BevyPlugin for Plugin {
fn build(&self, app: &mut App) {
app.add_enter_system(GameState::Limit, self::ui::spawn)
.add_system_set(
ConditionSet::new()
.run_in_state(GameState::Limit)
.with_system(handle_input.run_on_event::<ActionInputEvent>())
.with_system(play_sfx.run_on_event::<ActionInputEvent>())
.into(),
)
.add_exit_system(GameState::Limit, cleanup::<OverlayMarker>);
}
}

fn handle_input(
mut game_state_event_writer: EventWriter<SceneTransitionEvent>,
mut action_event_reader: EventReader<ActionInputEvent>,
) {
for action_event in action_event_reader.iter() {
if matches!(action_event.value, ActionInput::Select) {
game_state_event_writer.send(SceneTransitionEvent::selection(SelectionKind::Custom));
}
}
}

fn play_sfx(
mut action_event_reader: EventReader<ActionInputEvent>,
sounds: Res<Sounds>,
sfx: Res<AudioChannel<Sfx>>,
) {
for action_event in action_event_reader.iter() {
if matches!(action_event.value, ActionInput::Select) {
sfx.play(sounds.sfx_push_box.clone());
}
}
}
30 changes: 30 additions & 0 deletions src/scenes/limit/ui.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use bevy::prelude::*;

use crate::{
resources::prelude::*,
ui::{Container, GameText, Overlay, SimpleText},
};

pub fn spawn(mut commands: Commands, fonts: Res<Fonts>) {
let font = fonts.primary();

let overlay = Overlay::default();
let mut center = Container::height(140.0);

let mut reached_limit =
SimpleText::medium("You reached the limit\nfor the custom levels", font);
let press_button = SimpleText::small(
"Press SPACE to continue to the custom level selection",
font,
);

center.justify_between();
reached_limit.primary();

overlay.spawn(&mut commands, |parent| {
center.spawn(parent, |parent| {
reached_limit.spawn(parent);
press_button.spawn(parent);
});
});
}
2 changes: 2 additions & 0 deletions src/scenes/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod editor;
mod instructions;
mod level;
mod limit;
mod options;
mod passed;
mod selection;
Expand All @@ -16,6 +17,7 @@ impl BevyPlugin for Plugin {
app.add_plugin(title::Plugin)
.add_plugin(instructions::Plugin)
.add_plugin(editor::Plugin)
.add_plugin(limit::Plugin)
.add_plugin(passed::Plugin)
.add_plugin(options::Plugin)
.add_plugin(selection::Plugin)
Expand Down
4 changes: 3 additions & 1 deletion src/scenes/passed/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,10 @@ pub fn handle_text_input(

level_handles.insert_custom(uuid, asset_server.load(&levels_path));

let lower_level_name = level_name.to_lowercase();

save_file.insert_custom_level_record(
format!("{}${uuid}", *level_name),
format!("{lower_level_name}${uuid}"),
level.get_set_record(),
);

Expand Down
31 changes: 29 additions & 2 deletions src/scenes/selection/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
mod ui;

use std::{env, fs::remove_file, path::PathBuf};

use bevy::{app::Plugin as BevyPlugin, prelude::*};
use bevy_kira_audio::{AudioChannel, AudioControl};
use iyes_loopless::prelude::*;
Expand Down Expand Up @@ -51,7 +53,7 @@ fn handle_direction_input(
let max_value = if is_stock {
save_file.unlocked_levels()
} else {
save_file.total_custom_levels()
save_file.number_custom_levels()
};

selected_index = Some(if index < max_value {
Expand Down Expand Up @@ -83,6 +85,7 @@ fn handle_action_input(
mut scene_transition_event_writer: EventWriter<SceneTransitionEvent>,
mut query: Query<&mut GameButtonData>,
mut action_event_reader: EventReader<ActionInputEvent>,
mut save_file: ResMut<SaveFile>,
game_state: Res<CurrentState<GameState>>,
) {
let is_stock = game_state.0.get_selection_kind().is_stock();
Expand Down Expand Up @@ -114,6 +117,30 @@ fn handle_action_input(
SelectionKind::Stock
}));
}

ActionInput::Delete => {
for button in query.iter_mut() {
if button.selected && !is_stock {
let payload = button
.payload
.clone()
.expect("The button payload was empty");
let parsed_payload: Vec<&str> = payload.split('$').collect();
save_file.delete_custom_level_record(&payload);
save_file.save();
let levels_path = format!("levels/custom/{}.lvl", parsed_payload[1]);
let assets_path = format!("assets/{}", &levels_path);
let path = if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
PathBuf::from(manifest_dir).join(assets_path)
} else {
PathBuf::from(assets_path)
};
remove_file(path).expect("File cannot be removed");
scene_transition_event_writer
.send(SceneTransitionEvent::selection(SelectionKind::Custom));
}
}
}
ActionInput::Exit => {
scene_transition_event_writer.send(SceneTransitionEvent::title());
}
Expand All @@ -129,7 +156,7 @@ fn play_action_sfx(
) {
for action_event in action_event_reader.iter() {
match action_event.value {
ActionInput::Exit => {
ActionInput::Exit | ActionInput::Delete => {
sfx.play(sounds.sfx_push_box.clone());
}
ActionInput::Toggle => {
Expand Down
19 changes: 13 additions & 6 deletions src/scenes/selection/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ fn spawn_stock_buttons(parent: &mut ChildBuilder, save_file: &SaveFile, font: &H
}

fn spawn_custom_buttons(parent: &mut ChildBuilder, save_file: &SaveFile, font: &Handle<Font>) {
for (index, (key, record)) in save_file.enumerated_custom_records() {
for (index, (key, record)) in save_file.ordered_custom_records() {
let housing = Container::size_percentage(25.0, 25.0);
let split_key: Vec<&str> = key.split('$').collect();
let mut button = GameButton::new(split_key[0], font);
Expand All @@ -46,7 +46,7 @@ fn spawn_custom_buttons(parent: &mut ChildBuilder, save_file: &SaveFile, font: &
};

button.id(index);
button.payload(key.clone());
button.payload(key.clone().clone());

if index == 0 {
button.selected();
Expand All @@ -70,14 +70,15 @@ pub fn spawn(
let overlay = Overlay::extended();
let top = Container::auto_height();
let mut middle = Container::default();
let bottom = Container::auto_height();
let mut bottom = Container::auto_height();

let kind = game_state.0.get_selection_kind();
let mut title = SimpleText::medium(format!("Select a {} Level", kind.to_str()), font);
let press_button = SimpleText::small(
format!("Press ENTER to switch to {} levels", kind.toggle().to_str()),
let mut enter = SimpleText::small(
format!("(ENTER) - Switch to {} levels", kind.toggle().to_str()),
font,
);
let mut delete = SimpleText::small("(DELETE) - Remove a custom level", font);

title.primary();
middle
Expand All @@ -87,6 +88,11 @@ pub fn spawn(
.items_start()
.content_start();

enter.primary();
delete.primary();

bottom.row().justify_between();

overlay.spawn(&mut commands, |parent| {
top.spawn(parent, |parent| {
title.spawn(parent);
Expand All @@ -99,7 +105,8 @@ pub fn spawn(
}
});
bottom.spawn(parent, |parent| {
press_button.spawn(parent);
enter.spawn(parent);
delete.spawn(parent);
});
});
}

0 comments on commit 19b6905

Please sign in to comment.