aboutsummaryrefslogtreecommitdiffstats
path: root/src/client.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/client.rs')
-rw-r--r--src/client.rs123
1 files changed, 79 insertions, 44 deletions
diff --git a/src/client.rs b/src/client.rs
index ce48b4f..6fa6ff1 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -11,8 +11,8 @@ use crate::shared::health_event::*;
use crate::shared::imperative::*;
use crate::shared::player::*;
use crate::shared::projectile::*;
+use crate::shared::shape::*;
use crate::shared::stats::*;
-use crate::shared::*;
use bevy::input::keyboard::*;
use bevy::input::mouse::MouseButton;
use bevy::prelude::*;
@@ -24,9 +24,6 @@ use std::net::SocketAddr;
mod network;
-const PLAYER_HOVER_INDICATOR_RADIUS: f32 = 13.;
-const PLAYER_HOVER_RADIUS: f32 = 20.;
-
pub fn main(
server_addr: Option<SocketAddr>,
client_id: u64,
@@ -193,12 +190,12 @@ fn render_players(
mut commands: Commands,
mut materials: ResMut<Assets<ColorMaterial>>,
mut meshes: ResMut<Assets<Mesh>>,
- players: Query<(Entity, &PlayerPosition, &PlayerColor), Added<PlayerId>>,
+ players: Query<(Entity, &PlayerPosition, &PlayerColor, &Shape), Added<PlayerId>>,
) {
- for (entity, position, color) in players.iter() {
+ for (entity, position, color, shape) in players.iter() {
commands.entity(entity).insert(MaterialMesh2dBundle {
mesh: Mesh2dHandle(meshes.add(Circle {
- radius: PLAYER_RADIUS,
+ radius: shape.radius,
})),
material: materials.add(color.0),
transform: Transform::from_xyz(position.0.x, position.0.y, 0.),
@@ -275,7 +272,7 @@ fn move_players(mut players: Query<(&mut Transform, &PlayerPosition), Changed<Pl
}
fn buffer_input(
- players: Query<(&PlayerId, &PlayerPosition)>,
+ players: Query<(&PlayerId, &PlayerPosition, &Shape)>,
mut attack: ResMut<Attack>,
cameras: Query<(&Camera, &GlobalTransform)>,
client_id: Res<ClientId>,
@@ -303,7 +300,7 @@ fn buffer_input(
attack.0 = None;
}
Ability::Targeted(_) => {
- let Some((target_player, _)) =
+ let Some((target_player, _, _)) =
hovered_other_player(&cameras, &client_id, &players, &windows)
else {
return;
@@ -316,7 +313,7 @@ fn buffer_input(
}
},
None => {
- if let Some((target_player, _)) =
+ if let Some((target_player, _, _)) =
hovered_other_player(&cameras, &client_id, &players, &windows)
{
client.add_input(Inputs::Imperative(Imperative::AttackTarget(
@@ -378,15 +375,16 @@ fn choose_attack(
fn gizmos_hover_indicator(
cameras: Query<(&Camera, &GlobalTransform)>,
client_id: Res<ClientId>,
- hoverables: Query<(&PlayerId, &PlayerPosition)>,
+ hoverables: Query<(&PlayerId, &PlayerPosition, &Shape)>,
mut gizmos: Gizmos,
windows: Query<&Window>,
) {
- let Some((_, position)) = hovered_other_player(&cameras, &client_id, &hoverables, &windows)
+ let Some((_, position, shape)) =
+ hovered_other_player(&cameras, &client_id, &hoverables, &windows)
else {
return;
};
- gizmos.circle_2d(position.0, PLAYER_HOVER_INDICATOR_RADIUS, Color::GREEN);
+ gizmos.circle_2d(position.0, shape.radius + 1., Color::GREEN);
}
fn cursor_world_position(
@@ -409,22 +407,22 @@ fn world_to_viewport(cameras: &Query<(&Camera, &GlobalTransform)>, position: Vec
fn hovered_other_player(
cameras: &Query<(&Camera, &GlobalTransform)>,
client_id: &Res<ClientId>,
- hoverables: &Query<(&PlayerId, &PlayerPosition)>,
+ hoverables: &Query<(&PlayerId, &PlayerPosition, &Shape)>,
windows: &Query<&Window>,
-) -> Option<(PlayerId, PlayerPosition)> {
+) -> Option<(PlayerId, PlayerPosition, Shape)> {
let Some(world_position) = cursor_world_position(&windows, &cameras) else {
return None;
};
let mut hovered_player = None;
let mut hovered_distance = None;
- for (id, position) in hoverables.iter() {
+ for (id, position, shape) in hoverables.iter() {
if id.0 == client_id.0 {
continue;
}
let distance = position.0.distance(world_position);
- if distance < PLAYER_HOVER_RADIUS {
+ if distance < shape.radius + 5. {
if hovered_distance.map_or(true, |hovered_distance| distance < hovered_distance) {
- hovered_player = Some((*id, *position));
+ hovered_player = Some((*id, *position, *shape));
hovered_distance = Some(distance);
}
}
@@ -439,15 +437,25 @@ fn gizmos_attack_indicator(
effective_statses: Query<(&PlayerId, &EffectiveStats)>,
mut gizmos: Gizmos,
player_champions: Query<(&PlayerId, &Champion)>,
- player_positions: Query<(&PlayerId, &PlayerPosition)>,
+ player_positions: Query<(&PlayerId, &PlayerPosition, &Shape)>,
+ player_entities: Query<(&PlayerId, Entity)>,
+ pull_targets: Query<(Entity, &PlayerId, &PlayerPosition, &Shape)>,
+ dash_targets: Query<(Entity, &PlayerId, &PlayerPosition, &Shape)>,
+ player_shapes: Query<(&PlayerId, &Shape)>,
windows: Query<&Window>,
) {
+ let Some(entity) = player_entity(&client_id, &player_entities) else {
+ return;
+ };
let Some(position) = player_position(&client_id, &player_positions) else {
return;
};
let Some(champion) = player_champion(&client_id, &player_champions) else {
return;
};
+ let Some(shape) = player_shape(&client_id, &player_shapes) else {
+ return;
+ };
let Some(ability_slot) = attack.0 else {
return;
};
@@ -463,13 +471,14 @@ fn gizmos_attack_indicator(
let direction = world_position - position.0;
match ability {
DirectionalAbility::Dash(Dash { max_distance, .. }) => {
- let DashCollisionResult { dash_end, .. } = dash_collision(
- PlayerId(client_id.0),
- position.0,
+ let Some(DashCollisionResult { dash_end, .. }) = dash_collision(
+ entity,
direction.normalize_or_zero(),
max_distance,
- &player_positions,
- );
+ &dash_targets,
+ ) else {
+ return;
+ };
gizmos.arrow_2d(position.0, dash_end, Color::YELLOW);
}
DirectionalAbility::Flash(Flash { max_distance, .. }) => {
@@ -481,27 +490,26 @@ fn gizmos_attack_indicator(
);
}
DirectionalAbility::Pull(Pull { max_distance, .. }) => {
- let Some(PullCollision {
+ let Some(PullCollisionResult {
pull_end,
- collision_position,
+ collision_player_position,
..
}) = pull_collision(
- PlayerId(client_id.0),
- position.0,
+ entity,
direction.normalize_or_zero(),
max_distance,
- &player_positions,
+ &pull_targets,
)
else {
let pull_direction = -max_distance * direction.normalize_or_zero();
let pull_start = position.0 - pull_direction;
let pull_end = pull_start
- + (pull_direction.length() - 2. * PLAYER_RADIUS)
+ + (pull_direction.length() - 2. * shape.radius)
* pull_direction.normalize_or_zero();
gizmos.arrow_2d(pull_start, pull_end, Color::YELLOW);
return;
};
- gizmos.arrow_2d(collision_position, pull_end, Color::YELLOW);
+ gizmos.arrow_2d(collision_player_position.0, pull_end, Color::YELLOW);
}
DirectionalAbility::Spear(Spear { max_distance, .. }) => {
gizmos.arrow_2d(
@@ -518,11 +526,23 @@ fn gizmos_attack_indicator(
}
}
+fn player_entity(
+ client_id: &Res<ClientId>,
+ players: &Query<(&PlayerId, Entity)>,
+) -> Option<Entity> {
+ for (id, entity) in players.iter() {
+ if id.0 == client_id.0 {
+ return Some(entity);
+ }
+ }
+ None
+}
+
fn player_position(
client_id: &Res<ClientId>,
- players: &Query<(&PlayerId, &PlayerPosition)>,
+ players: &Query<(&PlayerId, &PlayerPosition, &Shape)>,
) -> Option<PlayerPosition> {
- for (id, position) in players.iter() {
+ for (id, position, _) in players.iter() {
if id.0 == client_id.0 {
return Some(*position);
}
@@ -554,12 +574,24 @@ fn player_champion(
None
}
+fn player_shape(client_id: &Res<ClientId>, players: &Query<(&PlayerId, &Shape)>) -> Option<Shape> {
+ for (id, shape) in players.iter() {
+ if id.0 == client_id.0 {
+ return Some(*shape);
+ }
+ }
+ None
+}
+
const HEALTH_OFFSET: f32 = 4.;
-fn render_health(players: Query<(&Health, &PlayerPosition, &EffectiveStats)>, mut gizmos: Gizmos) {
- for (health, position, effective_stats) in players.iter() {
- let start = position.0 + Vec2::new(-PLAYER_RADIUS, PLAYER_RADIUS + HEALTH_OFFSET);
- let end = position.0 + Vec2::new(PLAYER_RADIUS, PLAYER_RADIUS + HEALTH_OFFSET);
+fn render_health(
+ players: Query<(&Health, &PlayerPosition, &EffectiveStats, &Shape)>,
+ mut gizmos: Gizmos,
+) {
+ for (health, position, effective_stats, shape) in players.iter() {
+ let start = position.0 + Vec2::new(-shape.radius, shape.radius + HEALTH_OFFSET);
+ let end = position.0 + Vec2::new(shape.radius, shape.radius + HEALTH_OFFSET);
let health_start = start;
let health_end = start.lerp(end, health.health / effective_stats.0.max_health);
let px_per_health = (end.x - start.x) / effective_stats.0.max_health;
@@ -570,10 +602,13 @@ fn render_health(players: Query<(&Health, &PlayerPosition, &EffectiveStats)>, mu
}
}
-fn render_buffs(players: Query<(&Buffs, &PlayerPosition)>, mut gizmos: Gizmos) {
- for (buffs, position) in players.iter() {
- let mut start =
- position.0 + Vec2::new(-PLAYER_RADIUS + 1., PLAYER_RADIUS + HEALTH_OFFSET + 2.);
+fn render_buffs(players: Query<(&Buffs, &PlayerPosition, &Shape)>, mut gizmos: Gizmos) {
+ for (buffs, position, player_shape) in players.iter() {
+ let mut start = position.0
+ + Vec2::new(
+ -player_shape.radius + 1.,
+ player_shape.radius + HEALTH_OFFSET + 2.,
+ );
if buffs.haste.is_some() {
gizmos.rect_2d(start, 0., Vec2::new(2., 2.), Color::RED);
start = start + Vec2::new(3., 0.);
@@ -668,7 +703,7 @@ fn health_indicator_spawn(
cameras: Query<(&Camera, &GlobalTransform)>,
mut commands: Commands,
mut event_reader: EventReader<MessageEvent<HealthChanged>>,
- players: Query<(&PlayerId, &PlayerPosition)>,
+ players: Query<(&PlayerId, &PlayerPosition, &Shape)>,
) {
for event in event_reader.read() {
let HealthChanged(HealthEvent {
@@ -712,9 +747,9 @@ fn health_indicator_spawn(
fn any_player_position(
player_id: PlayerId,
- players: &Query<(&PlayerId, &PlayerPosition)>,
+ players: &Query<(&PlayerId, &PlayerPosition, &Shape)>,
) -> Option<PlayerPosition> {
- for (id, position) in players.iter() {
+ for (id, position, _) in players.iter() {
if *id == player_id {
return Some(*position);
}