From 7837ab49b0981fa3bde37d9afabc85df293dd76a Mon Sep 17 00:00:00 2001 From: Robert Garrett Date: Tue, 21 Oct 2025 13:55:58 -0500 Subject: [PATCH] Start button triggers connection & state change 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. --- client/src/main.rs | 33 ++++++++++++++++++++++++++++++--- client/src/ui.rs | 25 ++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/client/src/main.rs b/client/src/main.rs index 4eb40ff..7b62623 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -8,7 +8,10 @@ use bevy::{ use thiserror::Error; use tungstenite::{WebSocket, http::Response, stream::MaybeTlsStream}; -use crate::ui::{despawn_main_menu, spawn_main_menu}; +use crate::ui::{ + despawn_connection_wait_screen, despawn_main_menu, spawn_connection_wait_screen, + spawn_main_menu, +}; mod ui; @@ -23,6 +26,24 @@ fn main() { .add_systems(OnExit(GameState::MainMenu), despawn_main_menu) .add_observer(ui::button_hover_start) .add_observer(ui::button_hover_stop) + .add_systems( + OnEnter(GameState::Connecting), + ( + spawn_connection_wait_screen, + // Closure to immediately dispatch a setup-connection request. + |mut messages: MessageWriter| { + messages.write(WebSocketConnectionMessage::SetupConnection); + }, + ), + ) + .add_systems( + OnExit(GameState::Connecting), + despawn_connection_wait_screen, + ) + .add_systems( + Update, + (setup_connection, handle_tasks).run_if(in_state(GameState::Connecting)), + ) .add_systems(OnEnter(GameState::Playing), setup_game) .add_systems( Update, @@ -46,6 +67,7 @@ fn main() { #[derive(Clone, Debug, Eq, Hash, PartialEq, States)] enum GameState { MainMenu, + Connecting, Playing, ConnectionDemo, // TODO: Remove this state. } @@ -102,7 +124,7 @@ fn setup_game( struct Ball; /// Marker component for player paddles -/// +/// /// Maybe one for each player? /// Maybe it can hold the WebSocket, too. /// *Maybe* I can have one struct with an Option to know which @@ -216,12 +238,17 @@ fn setup_connection( /// /// The task is self-removing, so we don't need to delete the [`WsSetupTask`] /// component here. -fn handle_tasks(mut commands: Commands, mut transform_tasks: Query<&mut WsSetupTask>) { +fn handle_tasks( + mut commands: Commands, + mut transform_tasks: Query<&mut WsSetupTask>, + mut states: ResMut>, +) { for mut task in &mut transform_tasks { if let Some(result) = block_on(future::poll_once(&mut task.0)) { match result { Ok(mut commands_queue) => { commands.append(&mut commands_queue); + states.set(GameState::Playing); } Err(e) => info!("Connection failed. Err: {e:?}"), } diff --git a/client/src/ui.rs b/client/src/ui.rs index d569111..c3c0d78 100644 --- a/client/src/ui.rs +++ b/client/src/ui.rs @@ -33,7 +33,7 @@ pub fn spawn_main_menu(mut commands: Commands) { let mut start_button = cmds.spawn(button_bundle("Start game")); start_button.observe( |_trigger: On>, mut game_state: ResMut>| { - game_state.set(GameState::Playing); + game_state.set(GameState::Connecting); }, ); let mut quit_button = cmds.spawn(button_bundle("Quit Game")); @@ -58,6 +58,29 @@ pub fn despawn_main_menu( 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, With)>, +) { + 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.