From 47194894ca6d0d2e40d758b8594ffe05458430c8 Mon Sep 17 00:00:00 2001 From: Sofia Date: Tue, 21 Jul 2026 22:05:37 +0300 Subject: [PATCH] Add throwing the ball --- rust/src/ball.rs | 9 ++++++++- rust/src/game_manager.rs | 12 +++++++++--- rust/src/map.rs | 5 +++++ rust/src/net/network_manager.rs | 10 +++++++--- rust/src/player.rs | 22 +++++++++++++++++++++- 5 files changed, 50 insertions(+), 8 deletions(-) diff --git a/rust/src/ball.rs b/rust/src/ball.rs index ac14a8e..99b8abf 100644 --- a/rust/src/ball.rs +++ b/rust/src/ball.rs @@ -3,7 +3,10 @@ use godot::{ prelude::*, }; -use crate::player::{IPlayer, NetTransform}; +use crate::{ + net::util::NetVector3, + player::{IPlayer, NetTransform}, +}; #[derive(GodotClass)] #[class(base=RigidBody3D, init)] @@ -41,6 +44,10 @@ impl Ball { } } + pub fn get_velocity(&self) -> NetVector3 { + self.base().get_linear_velocity().into() + } + fn on_collision(&mut self, node: Gd) { if let Ok(player) = node.try_dynify::() && let Some(player_id) = player.dyn_bind().get_player_id() diff --git a/rust/src/game_manager.rs b/rust/src/game_manager.rs index 49d498c..2792eb9 100644 --- a/rust/src/game_manager.rs +++ b/rust/src/game_manager.rs @@ -303,15 +303,20 @@ impl Game { for player in s.players.clone() { s.spawn_player_server(player.id); } - s.spawn_ball(None, None); + s.spawn_ball(None, None, None); }); } } } - pub fn spawn_ball(&mut self, transform: Option, player_id: Option) { + pub fn spawn_ball( + &mut self, + transform: Option, + velocity: Option, + player_id: Option, + ) { if let Some(map) = &mut self.current_map { - let ball = map.bind_mut().spawn_ball(transform, player_id); + let ball = map.bind_mut().spawn_ball(transform, velocity, player_id); if let Some(ball) = &ball { self.world_ball = Some(ball.clone()); ball.signals() @@ -325,6 +330,7 @@ impl Game { { peer.broadcast_reliable(Package::SpawnBall( ball.bind().get_transform(), + ball.bind().get_velocity(), player_id, )); } diff --git a/rust/src/map.rs b/rust/src/map.rs index 017a6da..dbc0c6b 100644 --- a/rust/src/map.rs +++ b/rust/src/map.rs @@ -3,6 +3,7 @@ use godot::{classes::CharacterBody3D, prelude::*}; use crate::{ ball::Ball, game_manager::Game, + net::util::NetVector3, player::{IPlayer, LocalPlayer, NetTransform, RemotePlayer}, }; @@ -93,6 +94,7 @@ impl Map { pub fn spawn_ball( &mut self, transform: Option, + velocity: Option, player_id: Option, ) -> Option> { if let Some(ball_spawner) = self.ball_spawner.clone() @@ -107,6 +109,9 @@ impl Map { } else { ball.set_global_position(ball_spawner.get_global_position()); } + if let Some(velocity) = velocity { + ball.set_linear_velocity(velocity.into()); + } Some(ball) } else { None diff --git a/rust/src/net/network_manager.rs b/rust/src/net/network_manager.rs index 768239e..9a08403 100644 --- a/rust/src/net/network_manager.rs +++ b/rust/src/net/network_manager.rs @@ -258,9 +258,13 @@ impl INode for NetworkManager { .handle_kill(source_player_id, target_player_id); } } - Package::SpawnBall(transform, player_id) => { + Package::SpawnBall(transform, velocity, player_id) => { if let Some(game) = &mut Game::singleton() { - game.bind_mut().spawn_ball(Some(transform), player_id); + game.bind_mut().spawn_ball( + Some(transform), + Some(velocity), + player_id, + ); } } Package::DespawnBall => { @@ -594,7 +598,7 @@ pub enum Package { Shoot(u16, NetVector3, NetTransform, f32), TakeDamage(DamageSource, u16, i32), Kill(DamageSource, u16), - SpawnBall(NetTransform, Option), + SpawnBall(NetTransform, NetVector3, Option), DespawnBall, SwapWeapon(u16, WeaponType), } diff --git a/rust/src/player.rs b/rust/src/player.rs index e0c733f..3184b95 100644 --- a/rust/src/player.rs +++ b/rust/src/player.rs @@ -58,6 +58,7 @@ pub trait IPlayer { pub trait PlayerMovement { fn player_update(&mut self, delta: f64); fn drop_ball_common(&mut self, with_velocity: bool) -> bool; + fn get_look_dir(&self) -> Vector3; } impl PlayerMovement for T { @@ -87,7 +88,7 @@ impl PlayerMovement for T { if let Some(weapon) = self.get_weapon() && let Ok(_) = weapon.try_cast::() { - self.run_deferred(|s| { + self.run_deferred(move |s| { if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer && let PeerKind::Server(peer, _) = peer { @@ -98,11 +99,18 @@ impl PlayerMovement for T { )); if let Some(mut game) = Game::singleton() { if let Some(ball_origin) = &s.get_ball_origin() { + let velocity = if with_velocity { + s.get_look_dir() * 20. + } else { + Vector3::ZERO + }; + game.bind_mut().spawn_ball( Some(NetTransform { location: ball_origin.get_global_position().into(), rotation: ball_origin.get_global_rotation().into(), }), + Some(velocity.into()), s.get_player_id(), ); } @@ -114,6 +122,14 @@ impl PlayerMovement for T { false } } + + fn get_look_dir(&self) -> Vector3 { + if let Some(ball_origin) = self.get_ball_origin() { + ball_origin.get_global_basis().col_c().neg() + } else { + Vector3::ZERO + } + } } #[derive(GodotClass)] @@ -663,6 +679,10 @@ impl ICharacterBody3D for RemotePlayer { mesh.bind_mut().update_y_look(self.look_up); } + + if let Some(ball_origin) = &mut self.ball_origin { + ball_origin.set_rotation(Vector3::RIGHT * self.look_up); + } } }