diff options
author | Henauxg <19689618+Henauxg@users.noreply.github.com> | 2022-11-03 16:57:55 +0100 |
---|---|---|
committer | Henauxg <19689618+Henauxg@users.noreply.github.com> | 2022-11-03 16:57:55 +0100 |
commit | a6f63d755caf51cd9866ba5aaf0c9fd3c0d56bde (patch) | |
tree | 8c9a9498ea877d6df02893caddf5717e57152c0b /examples/breakout/server.rs | |
parent | 4103125aa0f3ad3368ccf97fbdae5eedbe6e7233 (diff) |
[breakout:example] Networked bricks spawn
Diffstat (limited to 'examples/breakout/server.rs')
-rw-r--r-- | examples/breakout/server.rs | 97 |
1 files changed, 92 insertions, 5 deletions
diff --git a/examples/breakout/server.rs b/examples/breakout/server.rs index 663cd00..fb430f4 100644 --- a/examples/breakout/server.rs +++ b/examples/breakout/server.rs @@ -15,9 +15,10 @@ use bevy_quinnet::{ use crate::{ protocol::{ClientMessage, PaddleInput, ServerMessage}, - Brick, Collider, Scoreboard, Velocity, BALL_SIZE, BALL_SPEED, BOTTOM_WALL, + Collider, Scoreboard, Velocity, BALL_SIZE, BALL_SPEED, BOTTOM_WALL, BRICK_SIZE, + GAP_BETWEEN_BRICKS, GAP_BETWEEN_BRICKS_AND_SIDES, GAP_BETWEEN_PADDLE_AND_BRICKS, GAP_BETWEEN_PADDLE_AND_FLOOR, LEFT_WALL, PADDLE_PADDING, PADDLE_SIZE, PADDLE_SPEED, RIGHT_WALL, - TIME_STEP, TOP_WALL, WALL_THICKNESS, + SERVER_PORT, TIME_STEP, TOP_WALL, WALL_THICKNESS, }; const GAP_BETWEEN_PADDLE_AND_BALL: f32 = 35.; @@ -58,13 +59,21 @@ pub(crate) struct Paddle { player_id: ClientId, } +pub type BrickId = u64; +#[derive(Component)] +pub(crate) struct Brick(BrickId); + #[derive(Component)] pub(crate) struct Ball; pub(crate) fn start_listening(mut server: ResMut<Server>) { server .start( - ServerConfigurationData::new("127.0.0.1".to_string(), 6000, "0.0.0.0".to_string()), + ServerConfigurationData::new( + "127.0.0.1".to_string(), + SERVER_PORT, + "0.0.0.0".to_string(), + ), CertificateRetrievalMode::GenerateSelfSigned, ) .unwrap(); @@ -219,7 +228,7 @@ pub(crate) fn apply_velocity(mut query: Query<(&mut Transform, &Velocity), With< } fn start_game(commands: &mut Commands, server: &mut ResMut<Server>, players: &ResMut<Players>) { - // Paddles + // Spawn paddles for (index, (client_id, _)) in players.map.iter().enumerate() { let paddle = spawn_paddle(commands, *client_id, &PADDLES_STARTING_POSITION[index]); server @@ -234,7 +243,7 @@ fn start_game(commands: &mut Commands, server: &mut ResMut<Server>, players: &Re .unwrap(); } - // Balls + // Spawn balls for (position, direction) in BALLS_STARTING_POSITION .iter() .zip(INITIAL_BALLS_DIRECTION.iter()) @@ -252,6 +261,84 @@ fn start_game(commands: &mut Commands, server: &mut ResMut<Server>, players: &Re .unwrap(); } + // Spawn bricks + // Negative scales result in flipped sprites / meshes, + // which is definitely not what we want here + assert!(BRICK_SIZE.x > 0.0); + assert!(BRICK_SIZE.y > 0.0); + + let total_width_of_bricks = (RIGHT_WALL - LEFT_WALL) - 2. * GAP_BETWEEN_BRICKS_AND_SIDES; + let bottom_edge_of_bricks = + BOTTOM_WALL + GAP_BETWEEN_PADDLE_AND_FLOOR + GAP_BETWEEN_PADDLE_AND_BRICKS; + let available_height_for_bricks = TOP_WALL + - bottom_edge_of_bricks + - (GAP_BETWEEN_PADDLE_AND_FLOOR + GAP_BETWEEN_PADDLE_AND_BRICKS); + + assert!(total_width_of_bricks > 0.0); + assert!(available_height_for_bricks > 0.0); + + // Given the space available, compute how many rows and columns of bricks we can fit + let n_columns = (total_width_of_bricks / (BRICK_SIZE.x + GAP_BETWEEN_BRICKS)).floor() as usize; + let n_rows = + (available_height_for_bricks / (BRICK_SIZE.y + GAP_BETWEEN_BRICKS)).floor() as usize; + let height_occupied_by_bricks = + n_rows as f32 * (BRICK_SIZE.y + GAP_BETWEEN_BRICKS) - GAP_BETWEEN_BRICKS; + let n_vertical_gaps = n_columns - 1; + + // Because we need to round the number of columns, + // the space on the top and sides of the bricks only captures a lower bound, not an exact value + let center_of_bricks = (LEFT_WALL + RIGHT_WALL) / 2.0; + let left_edge_of_bricks = center_of_bricks + // Space taken up by the bricks + - (n_columns as f32 / 2.0 * BRICK_SIZE.x) + // Space taken up by the gaps + - n_vertical_gaps as f32 / 2.0 * GAP_BETWEEN_BRICKS; + + // In Bevy, the `translation` of an entity describes the center point, + // not its bottom-left corner + let offset_x = left_edge_of_bricks + BRICK_SIZE.x / 2.; + let offset_y = bottom_edge_of_bricks + + BRICK_SIZE.y / 2. + + (available_height_for_bricks - height_occupied_by_bricks) / 2.; // Offset so that both players are at an equal distance of the bricks + + let mut brick_id = 0; + for row in 0..n_rows { + for column in 0..n_columns { + let brick_position = Vec2::new( + offset_x + column as f32 * (BRICK_SIZE.x + GAP_BETWEEN_BRICKS), + offset_y + row as f32 * (BRICK_SIZE.y + GAP_BETWEEN_BRICKS), + ); + + // brick + commands + .spawn() + .insert(Brick(brick_id)) + .insert_bundle(TransformBundle { + local: Transform { + translation: brick_position.extend(0.0), + scale: Vec3::new(BRICK_SIZE.x, BRICK_SIZE.y, 1.0), + ..default() + }, + ..default() + }) + .insert(Collider); + brick_id += 1; + } + } + server + .send_group_message( + players.map.keys().into_iter(), + ServerMessage::SpawnBricks { + offset: Vec2 { + x: offset_x, + y: offset_y, + }, + rows: n_rows, + columns: n_columns, + }, + ) + .unwrap(); + server .send_group_message(players.map.keys().into_iter(), ServerMessage::StartGame {}) .unwrap(); |