diff options
Diffstat (limited to 'examples/breakout/server.rs')
-rw-r--r-- | examples/breakout/server.rs | 81 |
1 files changed, 77 insertions, 4 deletions
diff --git a/examples/breakout/server.rs b/examples/breakout/server.rs index 8d79523..663cd00 100644 --- a/examples/breakout/server.rs +++ b/examples/breakout/server.rs @@ -3,7 +3,9 @@ use std::collections::HashMap; use bevy::{ prelude::{ default, Commands, Component, Entity, EventReader, Query, ResMut, Transform, Vec2, Vec3, + With, }, + sprite::collide_aabb::{collide, Collision}, transform::TransformBundle, }; use bevy_quinnet::{ @@ -13,9 +15,9 @@ use bevy_quinnet::{ use crate::{ protocol::{ClientMessage, PaddleInput, ServerMessage}, - Ball, Collider, Velocity, BALL_SIZE, BALL_SPEED, BOTTOM_WALL, GAP_BETWEEN_PADDLE_AND_FLOOR, - LEFT_WALL, PADDLE_PADDING, PADDLE_SIZE, PADDLE_SPEED, RIGHT_WALL, TIME_STEP, TOP_WALL, - WALL_THICKNESS, + Brick, Collider, Scoreboard, Velocity, BALL_SIZE, BALL_SPEED, BOTTOM_WALL, + GAP_BETWEEN_PADDLE_AND_FLOOR, LEFT_WALL, PADDLE_PADDING, PADDLE_SIZE, PADDLE_SPEED, RIGHT_WALL, + TIME_STEP, TOP_WALL, WALL_THICKNESS, }; const GAP_BETWEEN_PADDLE_AND_BALL: f32 = 35.; @@ -56,6 +58,9 @@ pub(crate) struct Paddle { player_id: ClientId, } +#[derive(Component)] +pub(crate) struct Ball; + pub(crate) fn start_listening(mut server: ResMut<Server>) { server .start( @@ -134,7 +139,7 @@ pub(crate) fn update_paddles( server .send_group_message( players.map.keys().into_iter(), - ServerMessage::PaddlePosition { + ServerMessage::PaddleMoved { entity: paddle_entity, position: paddle_transform.translation, }, @@ -145,6 +150,74 @@ pub(crate) fn update_paddles( } } +pub(crate) fn check_for_collisions( + mut commands: Commands, + mut server: ResMut<Server>, + mut scoreboard: ResMut<Scoreboard>, + mut ball_query: Query<(&mut Velocity, &Transform, Entity), With<Ball>>, + collider_query: Query<(Entity, &Transform, Option<&Brick>), With<Collider>>, +) { + for (mut ball_velocity, ball_transform, ball) in ball_query.iter_mut() { + let ball_size = ball_transform.scale.truncate(); + + // check collision with walls + for (collider_entity, transform, maybe_brick) in &collider_query { + let collision = collide( + ball_transform.translation, + ball_size, + transform.translation, + transform.scale.truncate(), + ); + if let Some(collision) = collision { + // Bricks should be despawned and increment the scoreboard on collision + if maybe_brick.is_some() { + scoreboard.score += 1; + commands.entity(collider_entity).despawn(); + } + + // reflect the ball when it collides + let mut reflect_x = false; + let mut reflect_y = false; + + // only reflect if the ball's velocity is going in the opposite direction of the + // collision + match collision { + Collision::Left => reflect_x = ball_velocity.x > 0.0, + Collision::Right => reflect_x = ball_velocity.x < 0.0, + Collision::Top => reflect_y = ball_velocity.y < 0.0, + Collision::Bottom => reflect_y = ball_velocity.y > 0.0, + Collision::Inside => { /* do nothing */ } + } + + // reflect velocity on the x-axis if we hit something on the x-axis + if reflect_x { + ball_velocity.x = -ball_velocity.x; + } + + // reflect velocity on the y-axis if we hit something on the y-axis + if reflect_y { + ball_velocity.y = -ball_velocity.y; + } + + server + .broadcast_message(ServerMessage::BallCollided { + entity: ball, + position: ball_transform.translation, + velocity: ball_velocity.0, + }) + .unwrap(); + } + } + } +} + +pub(crate) fn apply_velocity(mut query: Query<(&mut Transform, &Velocity), With<Ball>>) { + for (mut transform, velocity) in &mut query { + transform.translation.x += velocity.x * TIME_STEP; + transform.translation.y += velocity.y * TIME_STEP; + } +} + fn start_game(commands: &mut Commands, server: &mut ResMut<Server>, players: &ResMut<Players>) { // Paddles for (index, (client_id, _)) in players.map.iter().enumerate() { |