Improve how raycasting is done
This commit is contained in:
parent
33095ec1b9
commit
d4f4dc43b0
@ -1,4 +1,7 @@
|
|||||||
use godot::prelude::*;
|
use godot::{
|
||||||
|
classes::{PhysicsRayQueryParameters3D, World3D},
|
||||||
|
prelude::*,
|
||||||
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||||
@ -23,3 +26,33 @@ impl From<NetVector3> for Vector3 {
|
|||||||
Vector3::new(value.x, value.y, value.z)
|
Vector3::new(value.x, value.y, value.z)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cast_ray(from: Vector3, to: Vector3, world: Option<Gd<World3D>>) -> Option<RaycastResult> {
|
||||||
|
let ray = PhysicsRayQueryParameters3D::create(from, to);
|
||||||
|
if let Some(mut ray) = ray {
|
||||||
|
ray.set_collision_mask(0b110);
|
||||||
|
ray.set_hit_back_faces(false);
|
||||||
|
ray.set_hit_from_inside(false);
|
||||||
|
ray.set_collide_with_bodies(true);
|
||||||
|
if let Some(world) = world
|
||||||
|
&& let Some(mut space) = world.get_direct_space_state()
|
||||||
|
{
|
||||||
|
let results = space.intersect_ray(&ray);
|
||||||
|
if let Some(position) = results.get("position") {
|
||||||
|
Some(RaycastResult {
|
||||||
|
position: Vector3::from_variant(&position),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct RaycastResult {
|
||||||
|
pub position: Vector3,
|
||||||
|
}
|
||||||
|
|||||||
@ -17,7 +17,7 @@ use crate::{
|
|||||||
Package::{Jump, Shoot},
|
Package::{Jump, Shoot},
|
||||||
PeerKind,
|
PeerKind,
|
||||||
},
|
},
|
||||||
util::NetVector3,
|
util::{NetVector3, cast_ray},
|
||||||
},
|
},
|
||||||
soldier_mesh::SoldierMesh,
|
soldier_mesh::SoldierMesh,
|
||||||
ui::cli::CommandLinePanel,
|
ui::cli::CommandLinePanel,
|
||||||
@ -221,29 +221,13 @@ impl ICharacterBody3D for LocalPlayer {
|
|||||||
if event.is_action_pressed("shoot") {
|
if event.is_action_pressed("shoot") {
|
||||||
let pos = if let Some(camera) = &self.camera {
|
let pos = if let Some(camera) = &self.camera {
|
||||||
let forward = camera.get_global_basis().col_c().neg();
|
let forward = camera.get_global_basis().col_c().neg();
|
||||||
let ray = PhysicsRayQueryParameters3D::create(
|
match cast_ray(
|
||||||
camera.get_global_position(),
|
camera.get_global_position(),
|
||||||
camera.get_global_position() + forward * 10000.,
|
camera.get_global_position() + forward,
|
||||||
);
|
self.base().get_world_3d(),
|
||||||
if let Some(mut ray) = ray {
|
) {
|
||||||
ray.set_collision_mask(0b110);
|
Some(res) => Some(res.position),
|
||||||
ray.set_hit_back_faces(false);
|
None => Some(camera.get_global_position() + forward * 100.),
|
||||||
ray.set_hit_from_inside(false);
|
|
||||||
ray.set_collide_with_bodies(true);
|
|
||||||
if let Some(world) = self.base().get_world_3d()
|
|
||||||
&& let Some(mut space) = world.get_direct_space_state()
|
|
||||||
{
|
|
||||||
let results = space.intersect_ray(&ray);
|
|
||||||
if let Some(position) = results.get("position") {
|
|
||||||
Some(Vector3::from_variant(&position))
|
|
||||||
} else {
|
|
||||||
Some(camera.get_global_position() + forward * 100.)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|||||||
@ -3,6 +3,8 @@ use godot::{
|
|||||||
prelude::*,
|
prelude::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::net::util::cast_ray;
|
||||||
|
|
||||||
pub trait Weapon {
|
pub trait Weapon {
|
||||||
fn shoot(&mut self, to: Vector3, deal_damage: bool);
|
fn shoot(&mut self, to: Vector3, deal_damage: bool);
|
||||||
}
|
}
|
||||||
@ -27,16 +29,23 @@ impl Weapon for Raygun {
|
|||||||
emitter.play();
|
emitter.play();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(prefab) = &self.bullet_prefab {
|
if let Some(source) = &self.bullet_source {
|
||||||
let mut bullet = prefab.instantiate_as::<Beam>();
|
let target = cast_ray(source.get_global_position(), to, self.base().get_world_3d());
|
||||||
|
|
||||||
|
let dir = (to - source.get_global_position()).normalized();
|
||||||
|
let beam_end = target
|
||||||
|
.map(|r| r.position)
|
||||||
|
.unwrap_or(source.get_global_position() + dir * 100.);
|
||||||
|
|
||||||
|
if let Some(prefab) = &self.bullet_prefab {
|
||||||
|
let mut bullet = prefab.instantiate_as::<Beam>();
|
||||||
|
|
||||||
if let Some(source) = &self.bullet_source {
|
|
||||||
bullet.bind_mut().source = Some(source.get_global_position());
|
bullet.bind_mut().source = Some(source.get_global_position());
|
||||||
}
|
bullet.bind_mut().target = Some(beam_end);
|
||||||
bullet.bind_mut().target = Some(to);
|
|
||||||
|
|
||||||
if let Some(mut parent) = self.base().find_parent("map") {
|
if let Some(mut parent) = self.base().find_parent("map") {
|
||||||
parent.add_child(&bullet);
|
parent.add_child(&bullet);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user