Skip to content

Commit

Permalink
Improve level selection state
Browse files Browse the repository at this point in the history
  • Loading branch information
septum committed Dec 22, 2022
1 parent dff6b16 commit 47b02d5
Show file tree
Hide file tree
Showing 10 changed files with 78 additions and 49 deletions.
2 changes: 1 addition & 1 deletion src/resources/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub mod prelude {
pub use super::save_file::{SaveFile, SaveFileHandle};
pub use super::scene::SceneTransitionEvent;
pub use super::sounds::{Music, Sfx, Sounds, INITIAL_VOLUME};
pub use super::state::GameState;
pub use super::state::{GameState, SelectionKind};
pub use super::systems::cleanup;
}

Expand Down
6 changes: 3 additions & 3 deletions src/resources/scene.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::state::GameState;
use super::state::{GameState, SelectionKind};

pub struct SceneTransitionEvent {
pub state: GameState,
Expand Down Expand Up @@ -41,9 +41,9 @@ impl SceneTransitionEvent {
}
}

pub fn selection(custom: bool) -> Self {
pub fn selection(kind: SelectionKind) -> Self {
Self {
state: GameState::Selection(custom),
state: GameState::Selection { kind },
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/resources/sounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ 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 => 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
37 changes: 36 additions & 1 deletion src/resources/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,32 @@ use iyes_loopless::prelude::*;

use super::prelude::*;

#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub enum SelectionKind {
Stock,
Custom,
}

impl SelectionKind {
pub fn is_stock(&self) -> bool {
matches!(self, Self::Stock)
}

pub fn to_str(&self) -> &str {
match self {
Self::Stock => "Stock",
Self::Custom => "Custom",
}
}

pub fn toggle(&self) -> Self {
match self {
Self::Stock => Self::Custom,
Self::Custom => Self::Stock,
}
}
}

#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum GameState {
Loading,
Expand All @@ -11,11 +37,20 @@ pub enum GameState {
Editor,
Passed,
Options,
Selection(bool),
Selection { kind: SelectionKind },
Level,
Win,
}

impl GameState {
pub fn get_selection_kind(&self) -> &SelectionKind {
match self {
Self::Selection { kind } => kind,
_ => unreachable!("The GameState is not Selection"),
}
}
}

pub struct Plugin;

impl BevyPlugin for Plugin {
Expand Down
8 changes: 7 additions & 1 deletion src/scenes/level/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,13 @@ fn handle_action_input(
}
ActionInput::Exit => {
sfx.play(sounds.sfx_push_box.clone());
game_state_event_writer.send(SceneTransitionEvent::selection(!level.is_stock()));
game_state_event_writer.send(SceneTransitionEvent::selection(
if level.is_stock() {
SelectionKind::Stock
} else {
SelectionKind::Custom
},
));
}
_ => (),
}
Expand Down
3 changes: 2 additions & 1 deletion src/scenes/passed/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,8 @@ pub fn handle_text_input(
text.sections[0].value = String::new();

save_file.save();
game_state_event_writer.send(SceneTransitionEvent::selection(true));
game_state_event_writer
.send(SceneTransitionEvent::selection(SelectionKind::Custom));
}
}
_ => (),
Expand Down
35 changes: 17 additions & 18 deletions src/scenes/selection/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@ pub struct Plugin;

impl BevyPlugin for Plugin {
fn build(&self, app: &mut App) {
for custom in [false, true] {
app.add_enter_system(GameState::Selection(custom), self::ui::spawn)
for kind in [SelectionKind::Stock, SelectionKind::Custom] {
app.add_enter_system(GameState::Selection { kind }, self::ui::spawn)
.add_system_set(
ConditionSet::new()
.run_in_state(GameState::Selection(custom))
.run_in_state(GameState::Selection { kind })
.with_system(handle_action_input.run_on_event::<ActionInputEvent>())
.with_system(handle_direction_input.run_on_event::<DirectionInputEvent>())
.with_system(play_action_sfx.run_on_event::<ActionInputEvent>())
.with_system(play_direction_sfx.run_on_event::<DirectionInputEvent>())
.into(),
)
.add_exit_system(GameState::Selection(custom), cleanup::<OverlayMarker>);
.add_exit_system(GameState::Selection { kind }, cleanup::<OverlayMarker>);
}
}
}
Expand All @@ -35,9 +35,7 @@ fn handle_direction_input(
game_state: Res<CurrentState<GameState>>,
save_file: Res<SaveFile>,
) {
let GameState::Selection(is_custom_selection) = game_state.0 else {
unreachable!("The current game state is invalid, it should be Selection");
};
let is_stock = game_state.0.get_selection_kind().is_stock();

for direction_event in direction_event_reader.iter() {
let mut selected_index: Option<usize> = None;
Expand All @@ -50,10 +48,10 @@ fn handle_direction_input(
DirectionInput::Right => button.id + 1,
};

let max_value = if is_custom_selection {
save_file.total_custom_levels()
} else {
let max_value = if is_stock {
save_file.unlocked_levels()
} else {
save_file.total_custom_levels()
};

selected_index = Some(if index < max_value {
Expand Down Expand Up @@ -87,33 +85,34 @@ fn handle_action_input(
mut action_event_reader: EventReader<ActionInputEvent>,
game_state: Res<CurrentState<GameState>>,
) {
let GameState::Selection(is_custom_selection) = game_state.0 else {
unreachable!("The current game state is invalid, it should be Selection");
};
let is_stock = game_state.0.get_selection_kind().is_stock();

for action_event in action_event_reader.iter() {
match action_event.value {
ActionInput::Select => {
for button in query.iter_mut() {
if button.selected {
let kind = if is_custom_selection {
let kind = if is_stock {
LevelKind::Stock(button.id)
} else {
LevelKind::Custom(
button
.payload
.clone()
.expect("The button payload was empty"),
)
} else {
LevelKind::Stock(button.id)
};

level_insertion_event_writer.send(LevelInsertionEvent::new(kind));
}
}
}
ActionInput::Toggle => {
scene_transition_event_writer
.send(SceneTransitionEvent::selection(!is_custom_selection));
scene_transition_event_writer.send(SceneTransitionEvent::selection(if is_stock {
SelectionKind::Custom
} else {
SelectionKind::Stock
}));
}
ActionInput::Exit => {
scene_transition_event_writer.send(SceneTransitionEvent::title());
Expand Down
26 changes: 6 additions & 20 deletions src/scenes/selection/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,31 +65,17 @@ pub fn spawn(
fonts: Res<Fonts>,
save_file: Res<SaveFile>,
) {
let GameState::Selection(is_custom_selection) = game_state.0 else {
unreachable!("The current game state is invalid, it should be Selection");
};

let font = fonts.primary();

let overlay = Overlay::extended();
let top = Container::auto_height();
let mut middle = Container::default();
let bottom = Container::auto_height();

// TODO: Change this
let selection_kind = if is_custom_selection {
"Custom"
} else {
"Stock"
};
let next_selection_kind = if is_custom_selection {
"stock"
} else {
"custom"
};
let mut title = SimpleText::medium(format!("Select a {selection_kind} Level"), font);
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 {next_selection_kind} selection"),
format!("Press ENTER to switch to {} levels", kind.toggle().to_str()),
font,
);

Expand All @@ -106,10 +92,10 @@ pub fn spawn(
title.spawn(parent);
});
middle.spawn(parent, |parent| {
if is_custom_selection {
spawn_custom_buttons(parent, &save_file, font);
} else {
if kind.is_stock() {
spawn_stock_buttons(parent, &save_file, font);
} else {
spawn_custom_buttons(parent, &save_file, font);
}
});
bottom.spawn(parent, |parent| {
Expand Down
2 changes: 1 addition & 1 deletion src/scenes/title/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ fn handle_action_input(
match button.id {
PLAY_ID => {
game_state_event_writer
.send(SceneTransitionEvent::selection(false));
.send(SceneTransitionEvent::selection(SelectionKind::Stock));
}
INSTRUCTIONS_ID => {
game_state_event_writer.send(SceneTransitionEvent::instructions());
Expand Down
6 changes: 4 additions & 2 deletions src/scenes/win/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,16 @@ fn handle_action_input(
match &level.kind {
LevelKind::Stock(index) => {
if level.is_last() {
game_state_event_writer.send(SceneTransitionEvent::selection(false));
game_state_event_writer
.send(SceneTransitionEvent::selection(SelectionKind::Stock));
} else {
level_instertion_event_writer
.send(LevelInsertionEvent::new(LevelKind::Stock(index + 1)));
}
}
LevelKind::Custom(_) => {
game_state_event_writer.send(SceneTransitionEvent::selection(true));
game_state_event_writer
.send(SceneTransitionEvent::selection(SelectionKind::Custom));
}
LevelKind::Playtest(_) => {
unreachable!("A playtest level cannot be won");
Expand Down

0 comments on commit 47b02d5

Please sign in to comment.