Add proper shooting effect
This commit is contained in:
parent
dc30551227
commit
79f223cb21
BIN
godot/assets/particle.png
Normal file
BIN
godot/assets/particle.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
41
godot/assets/particle.png.import
Normal file
41
godot/assets/particle.png.import
Normal file
@ -0,0 +1,41 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://dawgsqbcveewg"
|
||||
path.s3tc="res://.godot/imported/particle.png-5e5e4f76b889a93c8b085c65be799145.s3tc.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/particle.png"
|
||||
dest_files=["res://.godot/imported/particle.png-5e5e4f76b889a93c8b085c65be799145.s3tc.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=true
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
||||
@ -14,7 +14,7 @@ size = Vector2(100, 100)
|
||||
[sub_resource type="BoxShape3D" id="BoxShape3D_1cgct"]
|
||||
size = Vector3(100, 0.01, 100)
|
||||
|
||||
[node name="map_0" type="Map" unique_id=914577955 node_paths=PackedStringArray("spawner")]
|
||||
[node name="map" type="Map" unique_id=914577955 node_paths=PackedStringArray("spawner")]
|
||||
spawner = NodePath("spawner")
|
||||
local_player = ExtResource("1_yjvui")
|
||||
remote_player = ExtResource("2_kcncr")
|
||||
@ -33,8 +33,8 @@ material_override = SubResource("StandardMaterial3D_u8vuu")
|
||||
mesh = SubResource("PlaneMesh_1cgct")
|
||||
|
||||
[node name="static_body_3d" type="StaticBody3D" parent="terrain" unique_id=203785193]
|
||||
collision_layer = 3
|
||||
collision_mask = 3
|
||||
collision_layer = 7
|
||||
collision_mask = 7
|
||||
|
||||
[node name="collision_shape_3d" type="CollisionShape3D" parent="terrain/static_body_3d" unique_id=1466526153]
|
||||
shape = SubResource("BoxShape3D_1cgct")
|
||||
|
||||
@ -4,21 +4,19 @@
|
||||
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_oh8vq"]
|
||||
|
||||
[node name="player" type="LocalPlayer" unique_id=863055906 node_paths=PackedStringArray("camera", "soldier_mesh", "sound_emitter")]
|
||||
[node name="player" type="LocalPlayer" unique_id=863055906 node_paths=PackedStringArray("camera", "soldier_mesh")]
|
||||
look_sensitivity = 1.5
|
||||
camera = NodePath("camera_3d")
|
||||
move_speed = 5.0
|
||||
soldier_mesh = NodePath("soldier_m")
|
||||
sound_emitter = NodePath("")
|
||||
collision_mask = 2
|
||||
collision_mask = 4
|
||||
|
||||
[node name="camera_3d" type="Camera3D" parent="." unique_id=1773137418]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.8724979, -0.2644562)
|
||||
current = true
|
||||
|
||||
[node name="soldier_m" parent="." unique_id=281995630 instance=ExtResource("1_jd651")]
|
||||
transform = Transform3D(-0.5, 0, -4.371139e-08, 0, 0.5, 0, 4.371139e-08, 0, -0.5, 0, 0, -1.1592964)
|
||||
visible = false
|
||||
transform = Transform3D(-0.5, 0, -4.371139e-08, 0, 0.5, 0, 4.371139e-08, 0, -0.5, 0.15878421, 0, 0.19227558)
|
||||
|
||||
[node name="collision_shape_3d2" type="CollisionShape3D" parent="." unique_id=442150782]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.0310049, 0)
|
||||
|
||||
@ -1,13 +1,19 @@
|
||||
[gd_scene format=3 uid="uid://cw7duhhjebypt"]
|
||||
|
||||
[ext_resource type="PackedScene" uid="uid://cg81784ct8gf5" path="res://mesh/raygun.tscn" id="1_ckadf"]
|
||||
[ext_resource type="PackedScene" uid="uid://ctslratcr8h6v" path="res://scenes/player/raygun_bullet.tscn" id="1_m84jv"]
|
||||
[ext_resource type="AudioStream" uid="uid://xxpkjhaovyd" path="res://assets/LaserWithRecoveryEdited.ogg" id="2_lxble"]
|
||||
|
||||
[node name="raygun" type="Weapon" unique_id=751705927 node_paths=PackedStringArray("sound_emitter")]
|
||||
[node name="raygun" type="Weapon" unique_id=751705927 node_paths=PackedStringArray("sound_emitter", "bullet_source")]
|
||||
sound_emitter = NodePath("sound_emitter")
|
||||
bullet_prefab = ExtResource("1_m84jv")
|
||||
bullet_source = NodePath("bullet_source")
|
||||
|
||||
[node name="Raygun" parent="." unique_id=1928455392 instance=ExtResource("1_ckadf")]
|
||||
|
||||
[node name="sound_emitter" type="AudioStreamPlayer3D" parent="." unique_id=1572422640]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.8420726, 0)
|
||||
stream = ExtResource("2_lxble")
|
||||
|
||||
[node name="bullet_source" type="Node3D" parent="." unique_id=211401237]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.36108458, -1.490972)
|
||||
|
||||
40
godot/scenes/player/raygun_bullet.tscn
Normal file
40
godot/scenes/player/raygun_bullet.tscn
Normal file
@ -0,0 +1,40 @@
|
||||
[gd_scene format=3 uid="uid://ctslratcr8h6v"]
|
||||
|
||||
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_3g557"]
|
||||
particle_flag_align_y = true
|
||||
radial_velocity_min = -500.0
|
||||
radial_velocity_max = -500.0
|
||||
scale_over_velocity_max = 1.0
|
||||
|
||||
[sub_resource type="Curve" id="Curve_dmbod"]
|
||||
_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(1, 0), 0.0, 0.0, 0, 0]
|
||||
point_count = 2
|
||||
|
||||
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_yxhor"]
|
||||
emission_enabled = true
|
||||
emission = Color(1, 0, 1, 1)
|
||||
emission_energy_multiplier = 4.47
|
||||
use_particle_trails = true
|
||||
|
||||
[sub_resource type="TubeTrailMesh" id="TubeTrailMesh_m77kh"]
|
||||
material = SubResource("StandardMaterial3D_yxhor")
|
||||
sections = 2
|
||||
section_length = 0.5
|
||||
section_rings = 5
|
||||
cap_top = false
|
||||
cap_bottom = false
|
||||
curve = SubResource("Curve_dmbod")
|
||||
|
||||
[node name="raygun_bullet" type="Bullet" unique_id=1238833478 node_paths=PackedStringArray("emitter")]
|
||||
emitter = NodePath("gpu_particles_3d")
|
||||
|
||||
[node name="gpu_particles_3d" type="GPUParticles3D" parent="." unique_id=1330763726]
|
||||
emitting = false
|
||||
amount = 1
|
||||
lifetime = 3.8899999999999997
|
||||
one_shot = true
|
||||
fixed_fps = 100
|
||||
trail_enabled = true
|
||||
trail_lifetime = 0.5
|
||||
process_material = SubResource("ParticleProcessMaterial_3g557")
|
||||
draw_pass_1 = SubResource("TubeTrailMesh_m77kh")
|
||||
@ -4,11 +4,11 @@
|
||||
|
||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_1cgct"]
|
||||
|
||||
[node name="player" type="RemotePlayer" unique_id=845968872 node_paths=PackedStringArray("soldier_mesh", "sound_emitter")]
|
||||
[node name="player" type="RemotePlayer" unique_id=845968872 node_paths=PackedStringArray("soldier_mesh")]
|
||||
move_speed = 5.0
|
||||
soldier_mesh = NodePath("soldier_m")
|
||||
sound_emitter = NodePath("")
|
||||
collision_mask = 2
|
||||
collision_layer = 2
|
||||
collision_mask = 4
|
||||
|
||||
[node name="soldier_m" parent="." unique_id=281995630 instance=ExtResource("1_e2ekk")]
|
||||
transform = Transform3D(-0.5, 0, -4.371139e-08, 0, 0.5, 0, 4.371139e-08, 0, -0.5, 0, 0, 0)
|
||||
|
||||
@ -335,12 +335,13 @@ impl Game {
|
||||
pub fn handle_shoot(
|
||||
&mut self,
|
||||
player_id: u16,
|
||||
to: Vector3,
|
||||
transform: NetPlayerTransform,
|
||||
look_up: f32,
|
||||
deal_damage: bool,
|
||||
) -> bool {
|
||||
if let Some(player) = self.find_player_mut(player_id) {
|
||||
player.try_shoot(transform, look_up, deal_damage)
|
||||
player.try_shoot(to, transform, look_up, deal_damage)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
@ -432,6 +433,7 @@ impl Player {
|
||||
|
||||
pub fn try_shoot(
|
||||
&mut self,
|
||||
to: Vector3,
|
||||
transform: NetPlayerTransform,
|
||||
look_up: f32,
|
||||
deal_damage: bool,
|
||||
@ -441,7 +443,7 @@ impl Player {
|
||||
.dyn_bind_mut()
|
||||
.apply_rotation(transform.rotation.into());
|
||||
character.dyn_bind_mut().apply_look_up(look_up);
|
||||
character.dyn_bind_mut().try_shoot(true)
|
||||
character.dyn_bind_mut().try_shoot(to, true)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
||||
@ -227,10 +227,15 @@ impl INode for NetworkManager {
|
||||
game.bind_mut().handle_jump(player_id);
|
||||
}
|
||||
}
|
||||
Package::Shoot(player_id, transform, look_up) => {
|
||||
Package::Shoot(player_id, to, transform, look_up) => {
|
||||
if let Some(game) = &mut Game::singleton() {
|
||||
game.bind_mut()
|
||||
.handle_shoot(player_id, transform, look_up, false);
|
||||
game.bind_mut().handle_shoot(
|
||||
player_id,
|
||||
to.into(),
|
||||
transform,
|
||||
look_up,
|
||||
false,
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
@ -384,7 +389,7 @@ impl INode for NetworkManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
Package::Shoot(_, transform, look_up) => {
|
||||
Package::Shoot(_, to, transform, look_up) => {
|
||||
if let Some(game) = &mut Game::singleton() {
|
||||
let player = game
|
||||
.bind()
|
||||
@ -392,10 +397,14 @@ impl INode for NetworkManager {
|
||||
.cloned();
|
||||
if let Some(player) = player {
|
||||
if game.bind_mut().handle_shoot(
|
||||
player.id, transform, look_up, true,
|
||||
player.id,
|
||||
to.into(),
|
||||
transform,
|
||||
look_up,
|
||||
true,
|
||||
) {
|
||||
peer.broadcast_reliable(Package::Shoot(
|
||||
player.id, transform, look_up,
|
||||
player.id, to, transform, look_up,
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -531,7 +540,7 @@ pub enum Package {
|
||||
Sync(HashMap<u16, SyncPackage>),
|
||||
SelfSync(SyncPackage),
|
||||
Jump(u16),
|
||||
Shoot(u16, NetPlayerTransform, f32),
|
||||
Shoot(u16, NetVector3, NetPlayerTransform, f32),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
use std::f32::consts::PI;
|
||||
use std::{f32::consts::PI, ops::Neg};
|
||||
|
||||
use godot::{
|
||||
classes::{
|
||||
AudioStreamPlayer3D, Camera3D, CharacterBody3D, ICharacterBody3D, Input, InputEvent,
|
||||
InputEventMouseMotion, input::MouseMode,
|
||||
InputEventMouseMotion, PhysicsRayQueryParameters3D, input::MouseMode,
|
||||
},
|
||||
obj::WithBaseField,
|
||||
prelude::*,
|
||||
@ -43,7 +43,7 @@ pub trait IPlayer {
|
||||
fn get_look_up(&self) -> f32;
|
||||
fn get_transform(&self) -> NetPlayerTransform;
|
||||
fn jump(&mut self);
|
||||
fn try_shoot(&mut self, deal_damage: bool) -> bool;
|
||||
fn try_shoot(&mut self, to: Vector3, deal_damage: bool) -> bool;
|
||||
}
|
||||
|
||||
pub trait PlayerMovement {
|
||||
@ -154,10 +154,10 @@ impl IPlayer for LocalPlayer {
|
||||
|
||||
fn apply_look_up(&mut self, _look: f32) {}
|
||||
|
||||
fn try_shoot(&mut self, deal_damage: bool) -> bool {
|
||||
fn try_shoot(&mut self, to: Vector3, deal_damage: bool) -> bool {
|
||||
if self.shoot_cd <= 0. {
|
||||
if let Some(weapon) = &mut self.weapon {
|
||||
weapon.bind_mut().shoot(Vector3::ZERO, deal_damage);
|
||||
weapon.bind_mut().shoot(to, deal_damage);
|
||||
}
|
||||
self.shoot_cd = 0.2;
|
||||
true
|
||||
@ -219,15 +219,52 @@ impl ICharacterBody3D for LocalPlayer {
|
||||
fn input(&mut self, event: Gd<InputEvent>) {
|
||||
if self.locked {
|
||||
if event.is_action_pressed("shoot") {
|
||||
let pos = if let Some(camera) = &self.camera {
|
||||
let forward = camera.get_global_basis().col_c().neg();
|
||||
let ray = PhysicsRayQueryParameters3D::create(
|
||||
camera.get_global_position(),
|
||||
camera.get_global_position() + forward * 10000.,
|
||||
);
|
||||
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) = 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 {
|
||||
None
|
||||
};
|
||||
|
||||
godot_print!("{:?}", pos);
|
||||
|
||||
if let Some(pos) = pos {
|
||||
if let Some(peer) = &mut NetworkManager::singleton().bind_mut().peer {
|
||||
match peer {
|
||||
PeerKind::Client(peer, addr) => {
|
||||
peer.send_reliable(addr, Shoot(0, self.get_transform(), self.look_up));
|
||||
peer.send_reliable(
|
||||
addr,
|
||||
Shoot(0, pos.into(), self.get_transform(), self.look_up),
|
||||
);
|
||||
}
|
||||
PeerKind::Server(peer, _) => {
|
||||
if self.try_shoot(true) {
|
||||
if self.try_shoot(pos, true) {
|
||||
peer.broadcast_reliable(Shoot(
|
||||
0,
|
||||
pos.into(),
|
||||
self.get_transform(),
|
||||
self.look_up,
|
||||
));
|
||||
@ -236,6 +273,7 @@ impl ICharacterBody3D for LocalPlayer {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Ok(event) = event.try_cast::<InputEventMouseMotion>() {
|
||||
let x = event.get_relative().x * 0.001 * self.look_sensitivity;
|
||||
@ -343,10 +381,10 @@ impl IPlayer for RemotePlayer {
|
||||
self.look_up = look;
|
||||
}
|
||||
|
||||
fn try_shoot(&mut self, deal_damage: bool) -> bool {
|
||||
fn try_shoot(&mut self, to: Vector3, deal_damage: bool) -> bool {
|
||||
if self.shoot_cd <= 0. {
|
||||
if let Some(weapon) = &mut self.weapon {
|
||||
weapon.bind_mut().shoot(Vector3::ZERO, deal_damage);
|
||||
weapon.bind_mut().shoot(to, deal_damage);
|
||||
}
|
||||
self.shoot_cd = 0.2;
|
||||
true
|
||||
|
||||
@ -1,10 +1,17 @@
|
||||
use godot::{classes::AudioStreamPlayer3D, prelude::*};
|
||||
use godot::{
|
||||
classes::{AudioStreamPlayer3D, GpuParticles3D, PhysicsRayQueryParameters3D},
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
#[derive(GodotClass)]
|
||||
#[class(base=Node3D, init)]
|
||||
pub struct Weapon {
|
||||
#[export]
|
||||
sound_emitter: Option<Gd<AudioStreamPlayer3D>>,
|
||||
#[export]
|
||||
bullet_prefab: Option<Gd<PackedScene>>,
|
||||
#[export]
|
||||
bullet_source: Option<Gd<Node3D>>,
|
||||
|
||||
base: Base<Node3D>,
|
||||
}
|
||||
@ -14,5 +21,50 @@ impl Weapon {
|
||||
if let Some(emitter) = &mut self.sound_emitter {
|
||||
emitter.play();
|
||||
}
|
||||
|
||||
if let Some(prefab) = &self.bullet_prefab {
|
||||
let mut bullet = prefab.instantiate_as::<Bullet>();
|
||||
if let Some(mut parent) = self.base().find_parent("map") {
|
||||
parent.add_child(&bullet);
|
||||
if let Some(source) = &self.bullet_source {
|
||||
bullet.set_global_position(source.get_global_position());
|
||||
}
|
||||
}
|
||||
bullet.bind_mut().target = Some(to);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(GodotClass)]
|
||||
#[class(base=Node3D, init)]
|
||||
pub struct Bullet {
|
||||
#[export]
|
||||
pub emitter: Option<Gd<GpuParticles3D>>,
|
||||
|
||||
pub target: Option<Vector3>,
|
||||
|
||||
alive_for: f64,
|
||||
|
||||
base: Base<Node3D>,
|
||||
}
|
||||
|
||||
#[godot_api]
|
||||
impl INode3D for Bullet {
|
||||
fn ready(&mut self) {
|
||||
if let Some(emitter) = &mut self.emitter {
|
||||
emitter.set_emitting(true);
|
||||
}
|
||||
}
|
||||
|
||||
fn process(&mut self, delta: f64) {
|
||||
self.alive_for += delta;
|
||||
if self.alive_for > 0.05 {
|
||||
let prev_pos = self.base().get_global_position();
|
||||
|
||||
if let Some(target) = self.target {
|
||||
let new_pos = prev_pos.lerp(target, 0.5);
|
||||
self.base_mut().set_position(new_pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user