Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions src/game/ball/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ use bevy_ggrs::prelude::*;

use super::GameState;
use super::components::Team;
use super::field::{CellClicked, Wall, toggle_cell};
use super::field::{CellClicked, Wall};
use super::item::spawn_item;
use super::paddle::{Paddle, move_paddles};

mod respawn;

const FIRST_BALL_SPEED: f32 = 300.0;
const BALL_RADIUS: f32 = 10.0;
pub const FIRST_BALL_SPEED: f32 = 300.0;
pub const BALL_RADIUS: f32 = 10.0;

pub struct BallPlugin;

Expand All @@ -24,10 +25,11 @@ impl Plugin for BallPlugin {
check_collision,
respawn::respawn_balls,
respawn::handle_respawning_balls,
respawn::despawn_stopped_balls,
)
.chain()
.after(move_paddles)
.before(toggle_cell)
.before(spawn_item)
.run_if(in_state(GameState::InGame)),
)
.rollback_component_with_copy::<Ball>()
Expand Down Expand Up @@ -140,7 +142,7 @@ fn check_collision(

// Check for cell collisions
for (cell_entity, cell, cell_team, cell_transform) in &q_cell {
if cell_team != ball_team {
if cell_team == ball_team {
continue;
}
let closest_point = Aabb2d::new(cell_transform.translation.truncate(), cell.half_size)
Expand All @@ -156,7 +158,10 @@ fn check_collision(
let normal = diff.normalize();
velocity.0 = velocity.reflect(normal);
ball_transform.translation += (normal * (ball.radius - diff.length())).extend(0.);
events.write(CellClicked { cell: cell_entity });
events.write(CellClicked {
cell: cell_entity,
team: *ball_team,
});
continue 'ball;
}
}
Expand Down
12 changes: 12 additions & 0 deletions src/game/ball/respawn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,15 @@ pub fn handle_respawning_balls(
}
}
}

#[allow(clippy::type_complexity)]
pub fn despawn_stopped_balls(
mut commands: Commands,
q_ball: Query<(Entity, &Velocity), (With<Ball>, Without<RespawningBall>)>,
) {
for (entity, velocity) in q_ball {
if velocity.0.length_squared() < 0.01 {
commands.entity(entity).despawn();
}
}
}
15 changes: 15 additions & 0 deletions src/game/components.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,18 @@ use bevy::prelude::*;

#[derive(Component, Deref, DerefMut, PartialEq, Clone, Copy)]
pub struct Team(pub usize);

impl Team {
pub const ITEM: Self = Self(2);

pub fn hue(&self) -> f32 {
match self.0 {
0 => 0.,
1 => 180.,
_ => 60.,
}
}
}

#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Deref, DerefMut)]
pub struct Count(pub usize);
63 changes: 37 additions & 26 deletions src/game/field/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
use bevy::prelude::*;
use bevy_ggrs::prelude::*;
use bevy_ggrs::{LocalPlayers, prelude::*};

use super::{GameState, components::Team, online::network_role::NetworkRole};
use super::{
GameState,
components::{Count, Team},
};

pub const FIELD_WIDTH: i32 = 10;
pub const FIELD_HEIGHT: i32 = 10;
pub const CELL_SIZE: f32 = 50.;
pub const CELL_THICKNESS: f32 = 5.;

pub struct FieldPlugin;

Expand Down Expand Up @@ -33,44 +41,40 @@ pub struct Cell {
#[derive(Event)]
pub struct CellClicked {
pub cell: Entity,
pub team: Team,
}

fn rotate(mut camera: Single<&mut Transform, With<Camera>>, role: Res<NetworkRole>) {
if matches!(*role, NetworkRole::Client) {
return;
fn rotate(mut camera: Single<&mut Transform, With<Camera>>, local_players: Res<LocalPlayers>) {
if local_players.0.first().map(|x| *x == 1).unwrap_or(false) {
camera.rotate_z(std::f32::consts::PI);
}
camera.rotate_z(std::f32::consts::PI);
}

fn setup_field(mut commands: Commands) {
let cell_size = 50.;
let cell_thickness = 5.;
let field_width = 10;
let field_height = 10;

// spawn cells
for i in 0..2 {
for x in -field_width / 2..field_width / 2 {
for y in 0..field_height {
for x in -FIELD_WIDTH / 2..FIELD_WIDTH / 2 {
for y in 0..FIELD_HEIGHT {
let team = Team(i);
commands
.spawn((
Cell {
half_size: Vec2::splat(cell_size / 2.),
half_size: Vec2::splat(CELL_SIZE / 2.),
},
Team(i),
team,
Sprite::from_color(
Color::hsl(180. * i as f32, 0.6, 0.7),
Vec2::splat(cell_size),
Color::hsl(team.hue(), 0.6, 0.7),
Vec2::splat(CELL_SIZE),
),
Transform::from_xyz(
(x as f32 + 0.5) * cell_size,
((1. - 2. * i as f32) * (y as f32 + 0.5)) * cell_size,
(x as f32 + 0.5) * CELL_SIZE,
((2. * i as f32 - 1.) * (y as f32 + 0.5)) * CELL_SIZE,
5.,
),
children![(
Sprite::from_color(
Color::hsl(180. * i as f32, 0.8, 0.7),
Vec2::splat(cell_size - cell_thickness)
Color::hsl(team.hue(), 0.8, 0.7),
Vec2::splat(CELL_SIZE - CELL_THICKNESS)
),
Transform::IDENTITY,
)],
Expand All @@ -82,8 +86,8 @@ fn setup_field(mut commands: Commands) {

// spawn walls
let wall_thickness = 1000.;
let wall_width = field_width as f32 * cell_size;
let wall_height = field_height as f32 * cell_size * 2.;
let wall_width = FIELD_WIDTH as f32 * CELL_SIZE;
let wall_height = FIELD_HEIGHT as f32 * CELL_SIZE * 2.;

let half_size = Vec2::new(wall_width, wall_thickness) / 2.;

Expand Down Expand Up @@ -129,10 +133,17 @@ fn setup_field(mut commands: Commands) {
pub fn toggle_cell(
mut q_cell: Query<&mut Team, With<Cell>>,
mut q_click: EventReader<CellClicked>,
mut count: Local<Count>,
) {
for event in q_click.read() {
if let Ok(mut team) = q_cell.get_mut(event.cell) {
team.0 = 1 - **team;
if 10 <= count.0 {
*team = Team::ITEM;
count.0 = 0;
} else {
*team = event.team;
}
count.0 += 1;
}
}
}
Expand All @@ -143,10 +154,10 @@ fn update_cell_color(
mut q_child: Query<&mut Sprite, Without<Cell>>,
) {
for (children, team, mut sprite) in q_cell {
sprite.color = Color::hsl(180. * team.0 as f32, 0.6, 0.7);
sprite.color = Color::hsl(team.hue(), 0.6, 0.7);
for child in children {
if let Ok(mut sprite) = q_child.get_mut(*child) {
sprite.color = Color::hsl(180. * team.0 as f32, 0.8, 0.7);
sprite.color = Color::hsl(team.hue(), 0.8, 0.7);
}
}
}
Expand Down
Loading