tutorial logic mostly works

main
Elijah C. Voigt 2 years ago
parent 0f9d9b27ea
commit 2946c89f36

@ -7,6 +7,7 @@ pub(crate) struct TutorialPlugin;
impl Plugin for TutorialPlugin {
fn build(&self, app: &mut App) {
app.add_state::<TutorialState>()
.init_resource::<SeenStates>()
.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
// Evaluate if a piece is selected
step.run_if(state_exists::<TutorialState>())
.run_if(not(in_state(TutorialState::None)))
.run_if(|keys: Res<Input<KeyCode>>| -> bool {
.run_if(
// A piece changes sides
any_component_changed::<game::Side>
// When a piece is selected, we
.or_else(any_component_added::<game::Selected>)
// A piece is de-selected
.or_else(any_component_removed::<game::Selected>())
// TEMP: The user hits 'enter'
.or_else(|keys: Res<Input<KeyCode>>| -> bool {
keys.just_pressed(KeyCode::Return)
}),
// Evaluate if a piece is selected
step.run_if(state_exists::<TutorialState>())
.run_if(not(in_state(TutorialState::None)))
.run_if(any_component_added::<game::Selected>),
// Evaluate if a piece is selected
step.run_if(state_exists::<TutorialState>())
.run_if(not(in_state(TutorialState::None)))
.run_if(any_component_removed::<game::Selected>()),
// Evaluate if a piece's side changes
step.run_if(state_exists::<TutorialState>())
.run_if(not(in_state(TutorialState::None)))
.run_if(any_component_changed::<game::Side>),
),
),
)
.add_systems(OnExit(GameState::Play), deactivate::<TutorialState>)
@ -215,18 +213,23 @@ fn initialize_tutorial(
})
}
#[derive(Debug, Resource, Default)]
struct SeenStates(HashSet<TutorialState>);
fn step(
pieces: Query<&game::Piece, Added<game::Selected>>,
transitions: Query<Entity, Changed<game::Side>>,
curr_state: Res<State<TutorialState>>,
mut next_state: ResMut<NextState<TutorialState>>,
mut seen: Local<HashSet<TutorialState>>,
mut seen: ResMut<SeenStates>,
) {
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 => {
// 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 queen_selected {
TutorialState::PieceQueen
// When a drone is selected for the first time...
} else if drone_selected {
TutorialState::PieceDrone
// When a pawn is selected for the first time...
} else if pawn_selected {
TutorialState::PiecePawn
} else {
panic!("This shouldn't be possible...!")
}
// 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
} 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 !(*seen).contains(&TutorialState::Ownership)
&& transitions.iter().count() > 0
{
else if ownership_check {
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 {
// 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
}
// One piece is selected
} else {
// When a queen is selected for the first time...
if pieces.iter().filter(|&p| *p == game::Piece::Queen).count() > 0
&& !(*seen).contains(&TutorialState::PieceQueen)
{
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)
{
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)
{
TutorialState::PiecePawn
} else {
panic!("This shouldn't be possible...!")
}
}
}
// After the outro, we exit the tutorial

Loading…
Cancel
Save