Add throwing the ball

This commit is contained in:
Sofia 2026-07-21 22:05:37 +03:00
parent 179f10e449
commit 47194894ca
5 changed files with 50 additions and 8 deletions

View File

@ -3,7 +3,10 @@ use godot::{
prelude::*, prelude::*,
}; };
use crate::player::{IPlayer, NetTransform}; use crate::{
net::util::NetVector3,
player::{IPlayer, NetTransform},
};
#[derive(GodotClass)] #[derive(GodotClass)]
#[class(base=RigidBody3D, init)] #[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<Node>) { fn on_collision(&mut self, node: Gd<Node>) {
if let Ok(player) = node.try_dynify::<dyn IPlayer>() if let Ok(player) = node.try_dynify::<dyn IPlayer>()
&& let Some(player_id) = player.dyn_bind().get_player_id() && let Some(player_id) = player.dyn_bind().get_player_id()

View File

@ -303,15 +303,20 @@ impl Game {
for player in s.players.clone() { for player in s.players.clone() {
s.spawn_player_server(player.id); 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<NetTransform>, player_id: Option<u16>) { pub fn spawn_ball(
&mut self,
transform: Option<NetTransform>,
velocity: Option<NetVector3>,
player_id: Option<u16>,
) {
if let Some(map) = &mut self.current_map { 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 { if let Some(ball) = &ball {
self.world_ball = Some(ball.clone()); self.world_ball = Some(ball.clone());
ball.signals() ball.signals()
@ -325,6 +330,7 @@ impl Game {
{ {
peer.broadcast_reliable(Package::SpawnBall( peer.broadcast_reliable(Package::SpawnBall(
ball.bind().get_transform(), ball.bind().get_transform(),
ball.bind().get_velocity(),
player_id, player_id,
)); ));
} }

View File

@ -3,6 +3,7 @@ use godot::{classes::CharacterBody3D, prelude::*};
use crate::{ use crate::{
ball::Ball, ball::Ball,
game_manager::Game, game_manager::Game,
net::util::NetVector3,
player::{IPlayer, LocalPlayer, NetTransform, RemotePlayer}, player::{IPlayer, LocalPlayer, NetTransform, RemotePlayer},
}; };
@ -93,6 +94,7 @@ impl Map {
pub fn spawn_ball( pub fn spawn_ball(
&mut self, &mut self,
transform: Option<NetTransform>, transform: Option<NetTransform>,
velocity: Option<NetVector3>,
player_id: Option<u16>, player_id: Option<u16>,
) -> Option<Gd<Ball>> { ) -> Option<Gd<Ball>> {
if let Some(ball_spawner) = self.ball_spawner.clone() if let Some(ball_spawner) = self.ball_spawner.clone()
@ -107,6 +109,9 @@ impl Map {
} else { } else {
ball.set_global_position(ball_spawner.get_global_position()); ball.set_global_position(ball_spawner.get_global_position());
} }
if let Some(velocity) = velocity {
ball.set_linear_velocity(velocity.into());
}
Some(ball) Some(ball)
} else { } else {
None None

View File

@ -258,9 +258,13 @@ impl INode for NetworkManager {
.handle_kill(source_player_id, target_player_id); .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() { 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 => { Package::DespawnBall => {
@ -594,7 +598,7 @@ pub enum Package {
Shoot(u16, NetVector3, NetTransform, f32), Shoot(u16, NetVector3, NetTransform, f32),
TakeDamage(DamageSource, u16, i32), TakeDamage(DamageSource, u16, i32),
Kill(DamageSource, u16), Kill(DamageSource, u16),
SpawnBall(NetTransform, Option<u16>), SpawnBall(NetTransform, NetVector3, Option<u16>),
DespawnBall, DespawnBall,
SwapWeapon(u16, WeaponType), SwapWeapon(u16, WeaponType),
} }

View File

@ -58,6 +58,7 @@ pub trait IPlayer {
pub trait PlayerMovement { pub trait PlayerMovement {
fn player_update(&mut self, delta: f64); fn player_update(&mut self, delta: f64);
fn drop_ball_common(&mut self, with_velocity: bool) -> bool; fn drop_ball_common(&mut self, with_velocity: bool) -> bool;
fn get_look_dir(&self) -> Vector3;
} }
impl<T: IPlayer + ICharacterBody3D + WithBaseField> PlayerMovement for T { impl<T: IPlayer + ICharacterBody3D + WithBaseField> PlayerMovement for T {
@ -87,7 +88,7 @@ impl<T: IPlayer + ICharacterBody3D + WithBaseField> PlayerMovement for T {
if let Some(weapon) = self.get_weapon() if let Some(weapon) = self.get_weapon()
&& let Ok(_) = weapon.try_cast::<BallWeapon>() && let Ok(_) = weapon.try_cast::<BallWeapon>()
{ {
self.run_deferred(|s| { self.run_deferred(move |s| {
if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer
&& let PeerKind::Server(peer, _) = peer && let PeerKind::Server(peer, _) = peer
{ {
@ -98,11 +99,18 @@ impl<T: IPlayer + ICharacterBody3D + WithBaseField> PlayerMovement for T {
)); ));
if let Some(mut game) = Game::singleton() { if let Some(mut game) = Game::singleton() {
if let Some(ball_origin) = &s.get_ball_origin() { 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( game.bind_mut().spawn_ball(
Some(NetTransform { Some(NetTransform {
location: ball_origin.get_global_position().into(), location: ball_origin.get_global_position().into(),
rotation: ball_origin.get_global_rotation().into(), rotation: ball_origin.get_global_rotation().into(),
}), }),
Some(velocity.into()),
s.get_player_id(), s.get_player_id(),
); );
} }
@ -114,6 +122,14 @@ impl<T: IPlayer + ICharacterBody3D + WithBaseField> PlayerMovement for T {
false 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)] #[derive(GodotClass)]
@ -663,6 +679,10 @@ impl ICharacterBody3D for RemotePlayer {
mesh.bind_mut().update_y_look(self.look_up); 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);
}
} }
} }