When the start button is pressed, switch to a "connecting" state. This triggers the spawning of the "connecting" UI message and the connection startup. When the connection task finishes, `fn handle_tasks()` collects it and pushes the CommandQueue into the main world just as before. In addition, it will change to the "playing" state, which triggers the despawning of the UI notice. There is no meaningful connection-error handling path. A failed connection will print a warning to stdout, and that is all. There is still no transmitter at all, nor is the receiver hooked up to one of the paddles.
127 lines
4.1 KiB
Rust
127 lines
4.1 KiB
Rust
//! All the UI elements for the Pong game client.
|
|
|
|
use bevy::{
|
|
color::palettes::css::{DARK_GRAY, GRAY},
|
|
prelude::*,
|
|
};
|
|
|
|
use crate::GameState;
|
|
|
|
pub const BTN_BORDER_COLOR: Color = Color::WHITE;
|
|
pub const BTN_BG_COLOR: Color = Color::BLACK;
|
|
pub const BTN_BG_SELECTED: Color = bevy::prelude::Color::Srgba(DARK_GRAY);
|
|
|
|
pub fn spawn_main_menu(mut commands: Commands) {
|
|
commands
|
|
.spawn((Node {
|
|
width: Val::Percent(100.0),
|
|
height: Val::Percent(100.0),
|
|
align_items: AlignItems::Center,
|
|
justify_content: JustifyContent::Center,
|
|
flex_direction: FlexDirection::Column,
|
|
..Default::default()
|
|
},))
|
|
.with_children(|cmds| {
|
|
cmds.spawn((
|
|
// TODO: A more sharp and square font, maybe "pixel art" bitmap
|
|
// to really get the chunky feel of Pong.
|
|
Text::new("Robert's Bad Pong Game"),
|
|
TextFont::from_font_size(50.0),
|
|
TextLayout::new_with_justify(Justify::Center),
|
|
TextShadow::default(),
|
|
));
|
|
let mut start_button = cmds.spawn(button_bundle("Start game"));
|
|
start_button.observe(
|
|
|_trigger: On<Pointer<Click>>, mut game_state: ResMut<NextState<GameState>>| {
|
|
game_state.set(GameState::Connecting);
|
|
},
|
|
);
|
|
let mut quit_button = cmds.spawn(button_bundle("Quit Game"));
|
|
quit_button.observe(
|
|
|_trigger: On<Pointer<Click>>, mut messages: MessageWriter<AppExit>| {
|
|
// Quit the game if the quit button was pressed.
|
|
messages.write(AppExit::Success);
|
|
},
|
|
);
|
|
});
|
|
}
|
|
|
|
/// Despawns the main menu (which is assumed to be the top-most node)
|
|
///
|
|
/// TODO: Add a marker component, but only in debug builds. A unit test can
|
|
/// assert this condition so I don't actually have to check it at runtime
|
|
/// on release builds.
|
|
pub fn despawn_main_menu(
|
|
mut commands: Commands,
|
|
top_node: Single<Entity, (With<Node>, Without<ChildOf>)>,
|
|
) {
|
|
commands.entity(top_node.into_inner()).despawn();
|
|
}
|
|
|
|
pub fn spawn_connection_wait_screen(mut commands: Commands) {
|
|
info!("Spawning connecting notice.");
|
|
commands.spawn((
|
|
Node {
|
|
width: Val::Percent(100.0),
|
|
height: Val::Percent(100.0),
|
|
align_items: AlignItems::Center,
|
|
justify_content: JustifyContent::Center,
|
|
flex_direction: FlexDirection::Column,
|
|
..Default::default()
|
|
},
|
|
children![Text::new("Connecting...")],
|
|
));
|
|
}
|
|
|
|
pub fn despawn_connection_wait_screen(
|
|
mut commands: Commands,
|
|
text_nodes: Single<Entity, (With<Node>, With<Text>)>,
|
|
) {
|
|
info!("Despawning connecting notice.");
|
|
commands.entity(text_nodes.into_inner()).despawn();
|
|
}
|
|
|
|
/// The basic bundle for generic buttons.
|
|
///
|
|
/// It's mostly so I don't have to copy & paste this everywhere I want to use it.
|
|
fn button_bundle(text: &str) -> impl Bundle {
|
|
(
|
|
Button,
|
|
Node {
|
|
width: Val::Px(150.0),
|
|
height: Val::Px(65.0),
|
|
border: UiRect::all(Val::Px(4.0)),
|
|
justify_content: JustifyContent::Center,
|
|
align_items: AlignItems::Center,
|
|
margin: UiRect::all(Val::Px(10.0)),
|
|
..Default::default()
|
|
},
|
|
BorderColor::all(BTN_BORDER_COLOR),
|
|
BorderRadius::ZERO,
|
|
BackgroundColor(BTN_BG_COLOR),
|
|
children![(
|
|
Text::new(text),
|
|
TextColor(GRAY.into()),
|
|
TextShadow::default(),
|
|
)],
|
|
)
|
|
}
|
|
|
|
pub fn button_hover_start(
|
|
trigger: On<Pointer<Over>>,
|
|
mut button_colors: Query<(&mut BackgroundColor, &mut BorderColor), With<Button>>,
|
|
) {
|
|
if let Ok((mut bg, mut _border)) = button_colors.get_mut(trigger.entity) {
|
|
bg.0 = BTN_BG_SELECTED;
|
|
}
|
|
}
|
|
|
|
pub fn button_hover_stop(
|
|
trigger: On<Pointer<Out>>,
|
|
mut button_colors: Query<(&mut BackgroundColor, &mut BorderColor), With<Button>>,
|
|
) {
|
|
if let Ok((mut bg, mut _border)) = button_colors.get_mut(trigger.entity) {
|
|
bg.0 = BTN_BG_COLOR;
|
|
}
|
|
}
|