selection-refactor
Elijah Voigt 2 years ago
parent 426292685a
commit 293f27aba9

@ -1,6 +1,6 @@
use crate::prelude::*; use crate::prelude::*;
pub struct AudioPlugin; pub(crate) struct AudioPlugin;
impl Plugin for AudioPlugin { impl Plugin for AudioPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {

@ -1,20 +1,114 @@
use bevy::{
asset::diagnostic::AssetCountDiagnosticsPlugin,
diagnostic::{
DiagnosticsStore, EntityCountDiagnosticsPlugin, FrameTimeDiagnosticsPlugin,
SystemInformationDiagnosticsPlugin,
},
input::{keyboard::KeyboardInput, ButtonState},
};
use crate::prelude::*; use crate::prelude::*;
pub struct DebugPlugin; pub(crate) struct DebugPlugin;
impl Plugin for DebugPlugin { impl Plugin for DebugPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_systems( app.add_plugins((
FrameTimeDiagnosticsPlugin,
EntityCountDiagnosticsPlugin::default(),
AssetCountDiagnosticsPlugin::<Gltf>::default(),
AssetCountDiagnosticsPlugin::<Image>::default(),
AssetCountDiagnosticsPlugin::<Scene>::default(),
AssetCountDiagnosticsPlugin::<Font>::default(),
SystemInformationDiagnosticsPlugin::default(),
))
.add_systems(Startup, init_debug_ui)
.add_systems(
Update, Update,
display_board.run_if(resource_exists::<DebugEnabled>()), (
toggle_debug_mode.run_if(on_event::<KeyboardInput>()),
display_diagnostics.run_if(resource_exists::<DebugEnabled>()),
toggle_debug_ui.run_if(resource_changed_or_removed::<DebugEnabled>()),
),
); );
} }
} }
/// Marker resource used to enable Debug mode when present /// Marker resource used to enable Debug mode when present
#[derive(Debug, Resource)] #[derive(Debug, Resource, Default)]
struct DebugEnabled; struct DebugEnabled;
fn display_board(board: Res<crate::game::Board>) { #[derive(Debug, Component)]
info!("{}", *board); struct DebugRoot;
fn toggle_debug_mode(
mut events: EventReader<KeyboardInput>,
enabled: Option<Res<DebugEnabled>>,
mut commands: Commands,
) {
events
.iter()
.filter(
|KeyboardInput {
state, key_code, ..
}| *state == ButtonState::Pressed && *key_code == Some(KeyCode::F3),
)
.for_each(|_| match enabled {
Some(_) => commands.remove_resource::<DebugEnabled>(),
None => commands.insert_resource(DebugEnabled),
});
}
fn toggle_debug_ui(
mut visibility: Query<&mut Visibility, (With<DebugRoot>, Without<Children>)>,
enabled: Option<Res<DebugEnabled>>,
) {
visibility.iter_mut().for_each(|mut vis| {
*vis = match enabled {
Some(_) => Visibility::Visible,
None => Visibility::Hidden,
}
});
}
fn init_debug_ui(mut commands: Commands) {
commands
.spawn((
NodeBundle {
style: Style { ..default() },
..default()
},
DebugRoot,
))
.with_children(|parent| {
parent.spawn((
TextBundle {
style: Style { ..default() },
..default()
},
DebugRoot,
));
});
}
fn display_diagnostics(
mut root: Query<&mut Text, With<DebugRoot>>,
diagnostics: Res<DiagnosticsStore>,
) {
root.iter_mut().for_each(|mut text| {
text.sections = diagnostics
.iter()
.map(|diagnostic| {
TextSection::new(
format!(
"{}: {:.0}\n",
diagnostic.name,
diagnostic.smoothed().unwrap_or(0.0),
),
TextStyle { ..default() },
)
})
.collect();
text.sections.sort_unstable_by(|a, b| a.value.cmp(&b.value));
});
} }

@ -6,7 +6,7 @@ use crate::{
const SCALE: f32 = 4.0; const SCALE: f32 = 4.0;
const TILE_SIZE: f32 = 16.0; const TILE_SIZE: f32 = 16.0;
pub struct Display2dPlugin; pub(crate) struct Display2dPlugin;
impl Plugin for Display2dPlugin { impl Plugin for Display2dPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
@ -24,9 +24,11 @@ impl Plugin for Display2dPlugin {
.run_if(any_with_component::<BoardIndex>()), .run_if(any_with_component::<BoardIndex>()),
cursor_position.run_if(in_state(GameState::Display2d)), cursor_position.run_if(in_state(GameState::Display2d)),
selected.run_if(resource_changed::<SelectedTile>()), selected.run_if(resource_changed::<SelectedTile>()),
menu::exit_to_menu.run_if(in_state(GameState::Display2d)),
), ),
) )
.add_systems(OnEnter(GameState::Display2d), (activate, draw_board)); .add_systems(OnEnter(GameState::Display2d), (activate, draw_board))
.add_systems(OnExit(GameState::Display2d), deactivate);
} }
} }
@ -44,15 +46,22 @@ struct Board2d;
#[derive(Debug, Component)] #[derive(Debug, Component)]
struct Piece2d; struct Piece2d;
#[derive(Debug, Component)]
struct Display2dCamera;
/// STARTUP: Initialize 2d gameplay Camera /// STARTUP: Initialize 2d gameplay Camera
fn initialize_camera(mut commands: Commands) { fn initialize_camera(mut commands: Commands) {
commands.spawn(Camera2dBundle { commands.spawn((
Display2dCamera,
Camera2dBundle {
camera: Camera { camera: Camera {
is_active: false, is_active: false,
..default() ..default()
}, },
..default() ..default()
}); },
UiCameraConfig { show_ui: true },
));
} }
/// STARTUP: Load sprite sheet and insert texture atlas /// STARTUP: Load sprite sheet and insert texture atlas
@ -85,6 +94,7 @@ fn initialize_board(sprite_sheet: Option<Res<SpriteSheet>>, mut commands: Comman
-SCALE * TILE_SIZE * 3.0 / 2.0, // Why 7 and 3?? -SCALE * TILE_SIZE * 3.0 / 2.0, // Why 7 and 3??
0.0, 0.0,
), ),
visibility: Visibility::Hidden,
..default() ..default()
}, },
Board2d, Board2d,
@ -166,7 +176,7 @@ fn draw_board(
} }
fn activate( fn activate(
mut cameras: Query<&mut Camera, With<Camera2d>>, mut cameras: Query<&mut Camera, With<Display2dCamera>>,
mut boards: Query<&mut Visibility, With<Board2d>>, mut boards: Query<&mut Visibility, With<Board2d>>,
) { ) {
cameras.iter_mut().for_each(|mut camera| { cameras.iter_mut().for_each(|mut camera| {
@ -177,6 +187,18 @@ fn activate(
}); });
} }
fn deactivate(
mut cameras: Query<&mut Camera, With<Display2dCamera>>,
mut boards: Query<&mut Visibility, With<Board2d>>,
) {
cameras.iter_mut().for_each(|mut camera| {
camera.is_active = false;
});
boards.iter_mut().for_each(|mut visibility| {
*visibility = Visibility::Hidden;
});
}
fn cursor_position( fn cursor_position(
mut events: EventReader<CursorMoved>, mut events: EventReader<CursorMoved>,
sprite_q: Query<( sprite_q: Query<(

@ -1,6 +1,6 @@
use crate::prelude::*; use crate::prelude::*;
pub struct Display3dPlugin; pub(crate) struct Display3dPlugin;
impl Plugin for Display3dPlugin { impl Plugin for Display3dPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
@ -10,7 +10,10 @@ impl Plugin for Display3dPlugin {
) )
.add_systems( .add_systems(
Update, Update,
(
initialize_board.run_if(resource_added::<ModelMap>()), initialize_board.run_if(resource_added::<ModelMap>()),
menu::exit_to_menu.run_if(in_state(GameState::Display3d)),
),
) )
.add_systems(OnEnter(GameState::Display3d), activate); .add_systems(OnEnter(GameState::Display3d), activate);
} }
@ -23,13 +26,16 @@ struct Board3d;
struct ModelMap; struct ModelMap;
fn initialize_camera(mut commands: Commands) { fn initialize_camera(mut commands: Commands) {
commands.spawn(Camera3dBundle { commands.spawn((
Camera3dBundle {
camera: Camera { camera: Camera {
is_active: false, is_active: false,
..default() ..default()
}, },
..default() ..default()
}); },
UiCameraConfig { show_ui: true },
));
} }
fn load_models(server: Res<AssetServer>, mut commands: Commands) { fn load_models(server: Res<AssetServer>, mut commands: Commands) {

@ -1,6 +1,6 @@
use crate::prelude::*; use crate::prelude::*;
pub struct GamePlugin; pub(crate) struct GamePlugin;
impl Plugin for GamePlugin { impl Plugin for GamePlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {

@ -3,6 +3,7 @@ mod debug;
mod display2d; mod display2d;
mod display3d; mod display3d;
mod game; mod game;
mod menu;
mod prelude; mod prelude;
use std::time::Duration; use std::time::Duration;
@ -40,6 +41,7 @@ fn main() {
display2d::Display2dPlugin, display2d::Display2dPlugin,
display3d::Display3dPlugin, display3d::Display3dPlugin,
game::GamePlugin, game::GamePlugin,
menu::MenuPlugin,
)) ))
.run(); .run();
} }
@ -61,15 +63,16 @@ fn loading(
let items = { sprites.ids() }; let items = { sprites.ids() };
let states = server.get_group_load_state(items); let states = server.get_group_load_state(items);
match states { match states {
LoadState::Loaded | LoadState::NotLoaded => next_state.set(GameState::Display2d), LoadState::Loaded | LoadState::NotLoaded => next_state.set(GameState::Menu),
_ => (), _ => (),
} }
} }
/// System for printing the current state
fn state(state: Option<Res<State<GameState>>>) { fn state(state: Option<Res<State<GameState>>>) {
state.map(|s| { state.map(|s| {
if s.is_added() || s.is_changed() { if s.is_added() || s.is_changed() {
info!("Updated state is {:?}", s); info!("State is {:?}", s);
} }
}); });
} }

@ -0,0 +1,211 @@
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_start,
handle_menu_quit,
bevy::window::close_on_esc,
interactive_button,
)
.run_if(in_state(GameState::Menu)),
)
.add_systems(OnEnter(GameState::Menu), activate)
.add_systems(OnExit(GameState::Menu), deactivate);
}
}
#[derive(Debug, Component)]
struct MenuCamera;
#[derive(Debug, Component)]
struct MenuRoot;
#[derive(Debug, Component)]
struct Start;
#[derive(Debug, Component)]
struct Quit;
fn init_menu_ui(mut commands: Commands) {
commands.spawn((
MenuCamera,
Camera2dBundle {
camera: Camera {
is_active: false,
..default()
},
..default()
},
UiCameraConfig { show_ui: true },
));
commands
.spawn((
MenuRoot,
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(),
..default()
},
))
.with_children(|parent| {
parent
.spawn((
Start,
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((
Start,
TextBundle::from_section(
"Start",
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 activate(
mut cameras: Query<&mut Camera, With<MenuCamera>>,
mut boards: Query<&mut Visibility, With<MenuRoot>>,
) {
cameras.iter_mut().for_each(|mut camera| {
camera.is_active = true;
});
boards.iter_mut().for_each(|mut visibility| {
*visibility = Visibility::Visible;
});
}
fn deactivate(
mut cameras: Query<&mut Camera, With<MenuCamera>>,
mut boards: Query<&mut Visibility, With<MenuRoot>>,
) {
cameras.iter_mut().for_each(|mut camera| {
camera.is_active = false;
});
boards.iter_mut().for_each(|mut visibility| {
*visibility = Visibility::Hidden;
});
}
fn handle_menu_start(
events: Query<&Interaction, (With<Start>, With<Button>, Changed<Interaction>)>,
mut next_state: ResMut<NextState<GameState>>,
) {
events
.iter()
.filter(|&interaction| *interaction == Interaction::Pressed)
.for_each(|_| next_state.set(GameState::Display2d))
}
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>>,
) {
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);
}
});
}
/// Used to return to the menu
pub(crate) fn exit_to_menu(
mut events: EventReader<KeyboardInput>,
mut next_state: ResMut<NextState<GameState>>,
) {
events
.iter()
.filter(
|KeyboardInput {
key_code, state, ..
}| {
*key_code == Some(KeyCode::Escape) && *state == ButtonState::Pressed
},
)
.for_each(|_| {
next_state.set(GameState::Menu);
})
}
Loading…
Cancel
Save