From 2946c89f36e5220c517f1371341bf8ae8d7fb5dd Mon Sep 17 00:00:00 2001 From: "Elijah C. Voigt" Date: Wed, 14 Feb 2024 21:11:50 -0800 Subject: [PATCH] tutorial logic mostly works --- src/tutorial.rs | 116 ++++++++++++++++++++++++------------------------ 1 file changed, 58 insertions(+), 58 deletions(-) diff --git a/src/tutorial.rs b/src/tutorial.rs index b01eda6..d5a73c9 100644 --- a/src/tutorial.rs +++ b/src/tutorial.rs @@ -7,6 +7,7 @@ pub(crate) struct TutorialPlugin; impl Plugin for TutorialPlugin { fn build(&self, app: &mut App) { app.add_state::() + .init_resource::() .add_systems( OnExit(GameState::Loading), initialize_tutorial @@ -20,24 +21,21 @@ impl Plugin for TutorialPlugin { .add_systems( Update, ( - // Run if we have a TutorialState *and* it is not TutorialState::None *and* we get a return keypress - step.run_if(state_exists::()) - .run_if(not(in_state(TutorialState::None))) - .run_if(|keys: Res>| -> bool { - keys.just_pressed(KeyCode::Return) - }), - // Evaluate if a piece is selected - step.run_if(state_exists::()) - .run_if(not(in_state(TutorialState::None))) - .run_if(any_component_added::), // Evaluate if a piece is selected step.run_if(state_exists::()) .run_if(not(in_state(TutorialState::None))) - .run_if(any_component_removed::()), - // Evaluate if a piece's side changes - step.run_if(state_exists::()) - .run_if(not(in_state(TutorialState::None))) - .run_if(any_component_changed::), + .run_if( + // A piece changes sides + any_component_changed:: + // When a piece is selected, we + .or_else(any_component_added::) + // A piece is de-selected + .or_else(any_component_removed::()) + // TEMP: The user hits 'enter' + .or_else(|keys: Res>| -> bool { + keys.just_pressed(KeyCode::Return) + }), + ), ), ) .add_systems(OnExit(GameState::Play), deactivate::) @@ -215,18 +213,23 @@ fn initialize_tutorial( }) } +#[derive(Debug, Resource, Default)] +struct SeenStates(HashSet); + fn step( pieces: Query<&game::Piece, Added>, transitions: Query>, curr_state: Res>, mut next_state: ResMut>, - mut seen: Local>, + mut seen: ResMut, ) { info!("Evalute tutorial state"); // Store the current state // Used to avoid doing a prevoius state again - (*seen).insert(curr_state.get().clone()); + seen.0.insert(curr_state.get().clone()); + + info!("Curr: {:?}, Seen: {:?}", curr_state.get(), seen); next_state.set(match curr_state.get() { // This transition is implicit. Menu transitions from None to Intro @@ -245,56 +248,53 @@ fn step( | TutorialState::PieceJump | TutorialState::Empty | TutorialState::Ownership => { - // There are no pieces selected - if pieces.is_empty() { - if (*seen).contains(&TutorialState::PieceIntro) - && (*seen).contains(&TutorialState::PieceQueen) - && (*seen).contains(&TutorialState::PieceDrone) - && (*seen).contains(&TutorialState::PiecePawn) - { - // And we have not touched on jumping yet - if !(*seen).contains(&TutorialState::PieceJump) { - TutorialState::PieceJump - } - // A piece moves sides, so talk about ownership - else if !(*seen).contains(&TutorialState::Ownership) - && transitions.iter().count() > 0 - { - TutorialState::Ownership - // We have visited all relevant tutorial points, say goodbye - } else if (*seen).contains(&TutorialState::PieceJump) - && (*seen).contains(&TutorialState::Ownership) - { - TutorialState::Outro - } - // We have not touched on jumping - else { - TutorialState::PieceEnd - } - // Default, empty (tutorial doesn't always need to show something) - } else { - TutorialState::Empty - } - // One piece is selected - } else { + // PERF: Doing all of this work up front results in unnecessary work + let piece_selected = !pieces.is_empty(); + let all_moves_done = seen.0.contains(&TutorialState::PieceIntro) + && seen.0.contains(&TutorialState::PieceQueen) + && seen.0.contains(&TutorialState::PieceDrone) + && seen.0.contains(&TutorialState::PiecePawn); + let ownership_done = seen.0.contains(&TutorialState::Ownership); + let ownership_check = !ownership_done && transitions.iter().count() > 0; + let jump_done = seen.0.contains(&TutorialState::PieceJump); + let queen_selected = pieces.iter().filter(|&p| *p == game::Piece::Queen).count() > 0; + let drone_selected = pieces.iter().filter(|&p| *p == game::Piece::Drone).count() > 0; + let pawn_selected = pieces.iter().filter(|&p| *p == game::Piece::Pawn).count() > 0; + + // A piece is selected, so talk about it + if piece_selected { // When a queen is selected for the first time... - if pieces.iter().filter(|&p| *p == game::Piece::Queen).count() > 0 - && !(*seen).contains(&TutorialState::PieceQueen) - { + if queen_selected { TutorialState::PieceQueen // When a drone is selected for the first time... - } else if pieces.iter().filter(|&p| *p == game::Piece::Drone).count() > 0 - && !(*seen).contains(&TutorialState::PieceDrone) - { + } else if drone_selected { TutorialState::PieceDrone // When a pawn is selected for the first time... - } else if pieces.iter().filter(|&p| *p == game::Piece::Pawn).count() > 0 - && !(*seen).contains(&TutorialState::PiecePawn) - { + } else if pawn_selected { TutorialState::PiecePawn } else { panic!("This shouldn't be possible...!") } + // There are no pieces selected + } else { + // All move, jump, and ownership tutorials done, say goodbye + if all_moves_done && jump_done && ownership_done { + TutorialState::Outro + } + // A piece moves sides, so talk about ownership + else if ownership_check { + TutorialState::Ownership + } + // We have not touched on jumping yet + else if all_moves_done && !jump_done { + TutorialState::PieceJump + // All pieces tutorialized, so prompt user to move pieces for more tutorial + } else if all_moves_done { + TutorialState::PieceEnd + // Default, empty (tutorial doesn't always need to show something) + } else { + TutorialState::Empty + } } } // After the outro, we exit the tutorial