use std::path::Path; use bevy::{ asset::{io::AssetSourceId, AssetPath}, ecs::query::QueryIter, prelude::*, }; use crate::{ gamepad::GamepadOne, player::Player, score::Score, GameStartEvent, GameState, START_POSITION, }; pub struct HUDPlugin; impl Plugin for HUDPlugin { fn build(&self, app: &mut App) { app.add_systems(Startup, setup); app.add_systems(Update, start_button_logic); } } fn setup(mut commands: Commands, asset_server: Res) { // let asset_path: AssetPath = "embedded://avoid_rs/assets/Xolonium-Regular.ttf".into(); let asset_path: AssetPath = "Xolonium-Regular.ttf".into(); let font: Handle<_> = asset_server.load(asset_path); // let path = Path::new("avoid-rs").join("assets/Xolonium-Regular.ttf"); // let source = AssetSourceId::from("embedded"); // let asset_path = AssetPath::from_path(&path).with_source(source); // let font: Handle<_> = asset_server.load(asset_path); // score UI, top middle commands .spawn(NodeBundle { style: Style { width: Val::Percent(100.0), align_items: AlignItems::Center, justify_content: JustifyContent::Center, ..Default::default() }, ..Default::default() }) .with_children(|parent| { parent.spawn(( TextBundle::from_section( "0", TextStyle { font: font.clone(), font_size: 64.0, ..Default::default() }, ) .with_text_justify(JustifyText::Center) .with_style(Style { justify_content: JustifyContent::Center, align_items: AlignItems::Center, ..Default::default() }), ScoreText, )); }); commands .spawn(NodeBundle { style: Style { width: Val::Percent(100.0), height: Val::Percent(100.0), align_items: AlignItems::Center, justify_content: JustifyContent::Center, ..Default::default() }, ..Default::default() }) .with_children(|parent| { // game info, middle of the screen parent.spawn(( TextBundle::from_section( "Dodge the creeps!", TextStyle { font: font.clone(), font_size: 64.0, ..Default::default() }, ) .with_text_justify(JustifyText::Center) .with_style(Style { justify_content: JustifyContent::Center, align_items: AlignItems::Center, ..Default::default() }), IntroMessageText, StartMenuUI, )); }); commands .spawn(NodeBundle { style: Style { width: Val::Percent(100.0), height: Val::Percent(90.0), align_items: AlignItems::End, justify_content: JustifyContent::Center, ..Default::default() }, ..Default::default() }) .with_children(|parent| { parent .spawn(( ButtonBundle { style: Style { width: Val::Px(200.0), height: Val::Px(100.0), border: UiRect::all(Val::Px(5.0)), // horizontally center child text justify_content: JustifyContent::Center, // vertically center child text align_items: AlignItems::Center, ..default() }, border_color: BorderColor(Color::BLACK), border_radius: BorderRadius::all(Val::Px(10.0)), background_color: Color::srgb(0.15, 0.15, 0.15).into(), ..default() }, StartButton, StartMenuUI, )) .with_children(|parent| { parent.spawn(TextBundle::from_section( "Start", TextStyle { font: font.clone(), font_size: 64.0, color: Color::srgb(0.9, 0.9, 0.9), }, )); }); }); } #[derive(Component)] pub struct ScoreText; #[derive(Component)] pub struct IntroMessageText; #[derive(Component)] pub struct StartButton; #[derive(Component)] pub struct StartMenuUI; fn start_button_logic( current_state: Res>, mut state: ResMut>, mut score: ResMut, gamepads: Res>, gamepad1: Option>, mut button: Query<(&Interaction, &mut BorderColor), With>, mut player_query: Query<(&mut Transform, &mut Visibility), With>, mut ui_elems_query: Query<&mut Visibility, (With, Without)>, mut score_text_query: Query<&mut Text, With>, ) { if current_state.get() == &GameState::Playing { return; }; let mut score_text = score_text_query.single_mut(); let (mut player_transform, mut player_visibility) = player_query.single_mut(); if let Some(gamepad) = gamepad1.as_deref() { let start_btn = GamepadButton { gamepad: gamepad.0, button_type: GamepadButtonType::Start, }; if gamepads.pressed(start_btn) { start_game( &mut score_text, &mut score, &mut state, &mut ui_elems_query, &mut player_visibility, &mut player_transform, ); } } let (interaction, mut border_color) = button.single_mut(); match *interaction { Interaction::Pressed => { start_game( &mut score_text, &mut score, &mut state, &mut ui_elems_query, &mut player_visibility, &mut player_transform, ); } Interaction::Hovered => border_color.0 = Color::WHITE, Interaction::None => border_color.0 = Color::BLACK, } } fn start_game( score_text: &mut Text, score: &mut Score, state: &mut NextState, ui_elems: &mut Query<&mut Visibility, (With, Without)>, player_visibility: &mut Visibility, player_transform: &mut Transform, ) { score.0 = 0; score_text.sections[0].value = format!("{}", score.0); state.set(GameState::Playing); for mut elem in ui_elems { *elem = Visibility::Hidden; } *player_visibility = Visibility::Visible; player_transform.translation = START_POSITION; }