You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
martian-chess/src/menu.rs

202 lines
6.4 KiB
Rust

use bevy::{
app::AppExit,
input::{keyboard::KeyboardInput, ButtonState},
window::PrimaryWindow,
};
use crate::prelude::*;
pub(crate) struct MenuPlugin;
impl Plugin for MenuPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, init_menu_ui)
.add_systems(
Update,
(
handle_menu_button,
handle_menu_quit,
bevy::window::close_on_esc,
interactive_button,
)
.run_if(in_state(GameState::Menu)),
)
.add_systems(OnEnter(GameState::Menu), activate::<Menu>)
.add_systems(OnExit(GameState::Menu), deactivate::<Menu>);
}
}
#[derive(Debug, Component)]
struct Menu;
#[derive(Debug, Component)]
struct Quit;
fn init_menu_ui(mut commands: Commands) {
commands
.spawn((
Menu,
NodeBundle {
style: Style {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
justify_content: JustifyContent::Center,
align_items: AlignItems::Center,
flex_direction: FlexDirection::Column,
position_type: PositionType::Absolute,
..default()
},
background_color: Color::NONE.into(),
visibility: Visibility::Hidden,
..default()
},
))
.with_children(|parent| {
parent
.spawn((
GameState::Play,
ButtonBundle {
style: Style {
padding: UiRect::all(Val::Px(5.0)),
margin: UiRect::all(Val::Px(5.0)),
..default()
},
background_color: Color::ORANGE.with_a(0.5).into(),
..default()
},
))
.with_children(|parent| {
parent.spawn((
GameState::Play,
TextBundle::from_section(
"Start",
TextStyle {
color: Color::BLACK,
font_size: 32.0,
..default()
},
),
));
});
parent
.spawn((
GameState::Credits,
ButtonBundle {
style: Style {
padding: UiRect::all(Val::Px(5.0)),
margin: UiRect::all(Val::Px(5.0)),
..default()
},
background_color: Color::ORANGE.with_a(0.5).into(),
..default()
},
))
.with_children(|parent| {
parent.spawn((
GameState::Credits,
TextBundle::from_section(
"Credits",
TextStyle {
color: Color::BLACK,
font_size: 32.0,
..default()
},
),
));
});
parent
.spawn((
Quit,
ButtonBundle {
style: Style {
padding: UiRect::all(Val::Px(5.0)),
margin: UiRect::all(Val::Px(5.0)),
..default()
},
background_color: Color::ORANGE.with_a(0.5).into(),
..default()
},
))
.with_children(|parent| {
parent.spawn((
Quit,
TextBundle::from_section(
"Quit",
TextStyle {
color: Color::BLACK,
font_size: 32.0,
..default()
},
),
));
});
});
}
fn handle_menu_button(
events: Query<(&Interaction, &GameState), (With<Button>, Changed<Interaction>)>,
mut next_gs: ResMut<NextState<GameState>>,
) {
events.iter().for_each(|(i, gs)| match i {
Interaction::Pressed => {
next_gs.set(gs.clone());
}
_ => (),
});
}
fn handle_menu_quit(
events: Query<&Interaction, (With<Quit>, With<Button>, Changed<Interaction>)>,
mut writer: EventWriter<AppExit>,
) {
events
.iter()
.filter(|&interaction| *interaction == Interaction::Pressed)
.for_each(|_| writer.send(AppExit));
}
fn interactive_button(
mut events: Query<(&mut BackgroundColor, &Interaction), (With<Button>, Changed<Interaction>)>,
mut window: Query<&mut Window, With<PrimaryWindow>>,
mut writer: EventWriter<audio::AudioEvent>,
) {
events
.iter_mut()
.for_each(|(mut bg_color, interaction)| match interaction {
Interaction::None => {
window.single_mut().cursor.icon = CursorIcon::Arrow;
bg_color.0.set_a(0.5);
}
Interaction::Hovered => {
window.single_mut().cursor.icon = CursorIcon::Hand;
bg_color.0.set_a(0.75);
}
Interaction::Pressed => {
window.single_mut().cursor.icon = CursorIcon::Grab;
bg_color.0.set_a(1.0);
writer.send(audio::AudioEvent::MenuSelect)
}
});
}
/// Used to return to the menu
pub(crate) fn exit_to_menu(
mut events: EventReader<KeyboardInput>,
mut next_state: ResMut<NextState<GameState>>,
) {
events
.read()
.filter(
|KeyboardInput {
key_code, state, ..
}| {
*key_code == Some(KeyCode::Escape) && *state == ButtonState::Pressed
},
)
.for_each(|_| {
next_state.set(GameState::Menu);
})
}