From 3d54d70e440c5ab1a7bfc16d5e38deb282b7d752 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torjus=20H=C3=A5kestad?= Date: Fri, 15 Aug 2025 04:08:08 +0200 Subject: [PATCH] game: add bullet and impacts --- game/Player.gd | 15 +-- game/assets/textures/circle_mask.png | 3 + game/assets/textures/circle_mask.png.import | 35 +++++++ game/assets/textures/cloud_noise.png | 3 + game/assets/textures/cloud_noise.png.import | 35 +++++++ game/assets/textures/solid_noise.png | 3 + game/assets/textures/solid_noise.png.import | 35 +++++++ game/bullet.gd | 29 ++++++ game/bullet.gd.uid | 1 + game/bullet.tscn | 20 ++++ game/bullet_decal.gd | 4 + game/bullet_decal.gd.uid | 1 + game/bullet_decal.tscn | 73 +++++++++++++- game/bullet_decal_smoke.gdshader | 14 +++ game/bullet_decal_smoke.gdshader.uid | 1 + game/bullet_decal_smoke.tres | 105 ++++++++++++++++++++ game/models/bullet.glb | 3 + game/models/bullet.glb.import | 37 +++++++ game/player.tscn | 4 +- 19 files changed, 411 insertions(+), 10 deletions(-) create mode 100644 game/assets/textures/circle_mask.png create mode 100644 game/assets/textures/circle_mask.png.import create mode 100644 game/assets/textures/cloud_noise.png create mode 100644 game/assets/textures/cloud_noise.png.import create mode 100644 game/assets/textures/solid_noise.png create mode 100644 game/assets/textures/solid_noise.png.import create mode 100644 game/bullet.gd create mode 100644 game/bullet.gd.uid create mode 100644 game/bullet.tscn create mode 100644 game/bullet_decal.gd create mode 100644 game/bullet_decal.gd.uid create mode 100644 game/bullet_decal_smoke.gdshader create mode 100644 game/bullet_decal_smoke.gdshader.uid create mode 100644 game/bullet_decal_smoke.tres create mode 100644 game/models/bullet.glb create mode 100644 game/models/bullet.glb.import diff --git a/game/Player.gd b/game/Player.gd index 2b4b1af..29cdab3 100644 --- a/game/Player.gd +++ b/game/Player.gd @@ -9,6 +9,8 @@ const FOV_LERP = 0.2 var gravity = ProjectSettings.get_setting("physics/3d/default_gravity") +var bullet = load("res://bullet.tscn") + @onready var head = $Head @onready var camera = $Head/PlayerCamera @onready var player_debug = $Head/PlayerCamera/PlayerDebug @@ -94,10 +96,9 @@ func play_shoot_effect(): muzzle_flash.restart() muzzle_flash.emitting = true - var collider = pistol_raycast.get_collider() - var col_point = pistol_raycast.get_collision_point() - if col_point and collider: - var b = bullet_decal.instantiate() - pistol_raycast.get_collider().add_child(b) - b.global_transform.origin = col_point - b.look_at(col_point + pistol_raycast.get_collision_normal(), Vector3.UP) + var parent = get_parent() + if parent: + var instance: Node3D = bullet.instantiate() + instance.position = pistol_raycast.global_position + instance.transform.basis = pistol_raycast.global_transform.basis + parent.add_child(instance) diff --git a/game/assets/textures/circle_mask.png b/game/assets/textures/circle_mask.png new file mode 100644 index 0000000..e0fbd40 --- /dev/null +++ b/game/assets/textures/circle_mask.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:38cc36de2f849623278e119a84d7bb8198f568039e9d84f273cf2da537ed1b66 +size 10432 diff --git a/game/assets/textures/circle_mask.png.import b/game/assets/textures/circle_mask.png.import new file mode 100644 index 0000000..0f1fa8b --- /dev/null +++ b/game/assets/textures/circle_mask.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b7n43gk3vc0cm" +path.s3tc="res://.godot/imported/circle_mask.png-cd67d89c80f71e333d9b72d12bb3dfb4.s3tc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} + +[deps] + +source_file="res://assets/textures/circle_mask.png" +dest_files=["res://.godot/imported/circle_mask.png-cd67d89c80f71e333d9b72d12bb3dfb4.s3tc.ctex"] + +[params] + +compress/mode=2 +compress/high_quality=false +compress/lossy_quality=0.7 +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/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 diff --git a/game/assets/textures/cloud_noise.png b/game/assets/textures/cloud_noise.png new file mode 100644 index 0000000..be12f72 --- /dev/null +++ b/game/assets/textures/cloud_noise.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:44e2245749d48889d8e864719c466d680b9e3ba87815b52e9441194ec4304171 +size 50577 diff --git a/game/assets/textures/cloud_noise.png.import b/game/assets/textures/cloud_noise.png.import new file mode 100644 index 0000000..a65906e --- /dev/null +++ b/game/assets/textures/cloud_noise.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://exuvqvppvyre" +path.s3tc="res://.godot/imported/cloud_noise.png-65ba324dbb61c2827eb3b66fb0445ac2.s3tc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} + +[deps] + +source_file="res://assets/textures/cloud_noise.png" +dest_files=["res://.godot/imported/cloud_noise.png-65ba324dbb61c2827eb3b66fb0445ac2.s3tc.ctex"] + +[params] + +compress/mode=2 +compress/high_quality=false +compress/lossy_quality=0.7 +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/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 diff --git a/game/assets/textures/solid_noise.png b/game/assets/textures/solid_noise.png new file mode 100644 index 0000000..7d4e922 --- /dev/null +++ b/game/assets/textures/solid_noise.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a3d5f8ce5c6f3fb83125a8d3ff2bbdefb8ffed9c6340a2acc81c03152b59866c +size 54837 diff --git a/game/assets/textures/solid_noise.png.import b/game/assets/textures/solid_noise.png.import new file mode 100644 index 0000000..a197cf0 --- /dev/null +++ b/game/assets/textures/solid_noise.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bs83wip0gghsc" +path.s3tc="res://.godot/imported/solid_noise.png-ea31f28dd51b66a6a0e60730a106aab8.s3tc.ctex" +metadata={ +"imported_formats": ["s3tc_bptc"], +"vram_texture": true +} + +[deps] + +source_file="res://assets/textures/solid_noise.png" +dest_files=["res://.godot/imported/solid_noise.png-ea31f28dd51b66a6a0e60730a106aab8.s3tc.ctex"] + +[params] + +compress/mode=2 +compress/high_quality=false +compress/lossy_quality=0.7 +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/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 diff --git a/game/bullet.gd b/game/bullet.gd new file mode 100644 index 0000000..3027896 --- /dev/null +++ b/game/bullet.gd @@ -0,0 +1,29 @@ +extends Node3D + +const SPEED = 80.0 + +@onready var raycast = $bullet/RayCast3D +@onready var bullet_decal = preload("res://bullet_decal.tscn") + +func _ready() -> void: + pass + +func _process(delta: float) -> void: + var next_pos = position + transform.basis * Vector3(0,0,-SPEED) * delta + raycast.visible = true + raycast.target_position = raycast.position + raycast.transform.basis * Vector3(0,0,SPEED) * delta * 1.5 + position = next_pos + + var collider = raycast.get_collider() + var col_point = raycast.get_collision_point() + if col_point and collider: + var b = bullet_decal.instantiate() + raycast.get_collider().add_child(b) + b.global_transform.origin = col_point + b.look_at(col_point + raycast.get_collision_normal(), Vector3.UP) + b.particles.emitting = true + b.smoke.emitting = true + queue_free() + +func _on_timer_timeout() -> void: + queue_free() diff --git a/game/bullet.gd.uid b/game/bullet.gd.uid new file mode 100644 index 0000000..707b40f --- /dev/null +++ b/game/bullet.gd.uid @@ -0,0 +1 @@ +uid://j5k8dvghgsf4 diff --git a/game/bullet.tscn b/game/bullet.tscn new file mode 100644 index 0000000..1d56d8a --- /dev/null +++ b/game/bullet.tscn @@ -0,0 +1,20 @@ +[gd_scene load_steps=3 format=3 uid="uid://c603t5do5rnqk"] + +[ext_resource type="Script" uid="uid://j5k8dvghgsf4" path="res://bullet.gd" id="1_v8qja"] +[ext_resource type="PackedScene" uid="uid://bg1q0xweaefoq" path="res://models/bullet.glb" id="2_t4vbm"] + +[node name="Bullet" type="Node3D"] +script = ExtResource("1_v8qja") + +[node name="bullet" parent="." instance=ExtResource("2_t4vbm")] + +[node name="RayCast3D" type="RayCast3D" parent="bullet"] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 0) +target_position = Vector3(0, -0.2, 0) + +[node name="Timer" type="Timer" parent="bullet"] +wait_time = 10.0 +one_shot = true +autostart = true + +[connection signal="timeout" from="bullet/Timer" to="." method="_on_timer_timeout"] diff --git a/game/bullet_decal.gd b/game/bullet_decal.gd new file mode 100644 index 0000000..3da22fc --- /dev/null +++ b/game/bullet_decal.gd @@ -0,0 +1,4 @@ +extends Node3D + +@onready var particles = $MeshInstance3D/GPUParticles3D +@onready var smoke = $MeshInstance3D/GPUParticles3D2 diff --git a/game/bullet_decal.gd.uid b/game/bullet_decal.gd.uid new file mode 100644 index 0000000..ddd9c16 --- /dev/null +++ b/game/bullet_decal.gd.uid @@ -0,0 +1 @@ +uid://rqqeb4ls4tgf diff --git a/game/bullet_decal.tscn b/game/bullet_decal.tscn index d0e8d8f..d1cd8a9 100644 --- a/game/bullet_decal.tscn +++ b/game/bullet_decal.tscn @@ -1,4 +1,7 @@ -[gd_scene load_steps=3 format=3 uid="uid://5dqpmmbur7v6"] +[gd_scene load_steps=15 format=3 uid="uid://5dqpmmbur7v6"] + +[ext_resource type="Script" uid="uid://rqqeb4ls4tgf" path="res://bullet_decal.gd" id="1_mfh3f"] +[ext_resource type="Shader" uid="uid://d4ml3kj8ympbf" path="res://bullet_decal_smoke.tres" id="2_nqa4f"] [sub_resource type="PlaneMesh" id="PlaneMesh_q27hx"] size = Vector2(0.05, 0.05) @@ -7,9 +10,77 @@ orientation = 2 [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_mfh3f"] albedo_color = Color(0, 0, 0, 1) +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_q27hx"] +albedo_color = Color(0, 0, 0, 1) + +[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_mfh3f"] +direction = Vector3(0, 0, -1) +initial_velocity_min = 5.0 +initial_velocity_max = 5.0 + +[sub_resource type="BoxMesh" id="BoxMesh_nqa4f"] +size = Vector3(0.05, 0.05, 0.05) + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_6cwkj"] +render_priority = 0 +shader = ExtResource("2_nqa4f") + +[sub_resource type="Curve" id="Curve_nqa4f"] +_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(0.60628, 0.717391), -1.24468, -1.24468, 0, 0, Vector2(0.978261, 0), 0.0, 0.0, 0, 0] +point_count = 3 + +[sub_resource type="CurveTexture" id="CurveTexture_6cwkj"] +curve = SubResource("Curve_nqa4f") + +[sub_resource type="Gradient" id="Gradient_mp8ng"] + +[sub_resource type="GradientTexture1D" id="GradientTexture1D_mi8h0"] +gradient = SubResource("Gradient_mp8ng") + +[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_nqa4f"] +particle_flag_align_y = true +particle_flag_rotate_y = true +angle_min = -180.0 +angle_max = 180.0 +direction = Vector3(0, -1, 1) +spread = 0.0 +initial_velocity_min = 1.8 +initial_velocity_max = 2.3 +angular_velocity_min = -50.0 +angular_velocity_max = 50.0 +gravity = Vector3(0, 0, 0) +color_ramp = SubResource("GradientTexture1D_mi8h0") +alpha_curve = SubResource("CurveTexture_6cwkj") + +[sub_resource type="QuadMesh" id="QuadMesh_8hcic"] + [node name="BulletDecal" type="Node3D"] +script = ExtResource("1_mfh3f") [node name="MeshInstance3D" type="MeshInstance3D" parent="."] transform = Transform3D(1, 0, 0, 0, -1, -8.74228e-08, 0, 8.74228e-08, -1, 0, 0, -0.00702295) mesh = SubResource("PlaneMesh_q27hx") surface_material_override/0 = SubResource("StandardMaterial3D_mfh3f") + +[node name="GPUParticles3D" type="GPUParticles3D" parent="MeshInstance3D"] +transform = Transform3D(1, 0, 0, 0, -1, 8.74228e-08, 0, -8.74228e-08, -1, 0, 5.15351e-11, -0.000589493) +visible = false +material_override = SubResource("StandardMaterial3D_q27hx") +emitting = false +amount = 16 +lifetime = 1.5 +one_shot = true +explosiveness = 1.0 +process_material = SubResource("ParticleProcessMaterial_mfh3f") +draw_pass_1 = SubResource("BoxMesh_nqa4f") + +[node name="GPUParticles3D2" type="GPUParticles3D" parent="MeshInstance3D"] +material_override = SubResource("ShaderMaterial_6cwkj") +emitting = false +amount = 16 +lifetime = 0.5 +one_shot = true +explosiveness = 0.86 +fixed_fps = 60 +process_material = SubResource("ParticleProcessMaterial_nqa4f") +draw_pass_1 = SubResource("QuadMesh_8hcic") diff --git a/game/bullet_decal_smoke.gdshader b/game/bullet_decal_smoke.gdshader new file mode 100644 index 0000000..d96ec45 --- /dev/null +++ b/game/bullet_decal_smoke.gdshader @@ -0,0 +1,14 @@ +shader_type spatial; + +void vertex() { + // Called for every vertex the material is visible on. +} + +void fragment() { + // Called for every pixel the material is visible on. +} + +//void light() { +// // Called for every pixel for every light affecting the material. +// // Uncomment to replace the default light processing function with this one. +//} diff --git a/game/bullet_decal_smoke.gdshader.uid b/game/bullet_decal_smoke.gdshader.uid new file mode 100644 index 0000000..d142593 --- /dev/null +++ b/game/bullet_decal_smoke.gdshader.uid @@ -0,0 +1 @@ +uid://buhpmxsxpx5iv diff --git a/game/bullet_decal_smoke.tres b/game/bullet_decal_smoke.tres new file mode 100644 index 0000000..9521514 --- /dev/null +++ b/game/bullet_decal_smoke.tres @@ -0,0 +1,105 @@ +[gd_resource type="VisualShader" load_steps=10 format=3 uid="uid://d4ml3kj8ympbf"] + +[ext_resource type="Texture2D" uid="uid://exuvqvppvyre" path="res://assets/textures/cloud_noise.png" id="1_exml1"] +[ext_resource type="Texture2D" uid="uid://b7n43gk3vc0cm" path="res://assets/textures/circle_mask.png" id="2_3sobh"] + +[sub_resource type="VisualShaderNodeTexture" id="VisualShaderNodeTexture_mjuxj"] +output_port_for_preview = 0 +expanded_output_ports = [0] +texture = ExtResource("1_exml1") + +[sub_resource type="VisualShaderNodeTexture" id="VisualShaderNodeTexture_xamyu"] +expanded_output_ports = [0] +texture = ExtResource("2_3sobh") + +[sub_resource type="VisualShaderNodeInput" id="VisualShaderNodeInput_qilve"] +expanded_output_ports = [0] +input_name = "color" + +[sub_resource type="VisualShaderNodeRemap" id="VisualShaderNodeRemap_bocjt"] +default_input_values = [1, 0.0, 2, 1.0, 3, 0.0, 4, 8.0] + +[sub_resource type="VisualShaderNodeFloatOp" id="VisualShaderNodeFloatOp_t3qas"] +operator = 2 + +[sub_resource type="VisualShaderNodeInput" id="VisualShaderNodeInput_586rk"] +expanded_output_ports = [0] +input_name = "color" + +[sub_resource type="VisualShaderNodeFloatOp" id="VisualShaderNodeFloatOp_74lg2"] +operator = 2 + +[resource] +code = "shader_type spatial; +render_mode blend_mix, depth_draw_opaque, cull_back, diffuse_lambert, specular_schlick_ggx; + +uniform sampler2D tex_frg_2; +uniform sampler2D tex_frg_3; + + + +void fragment() { +// Input:4 + vec4 n_out4p0 = COLOR; + float n_out4p1 = n_out4p0.r; + + + float n_out5p0; +// Remap:5 + float n_in5p1 = 0.00000; + float n_in5p2 = 1.00000; + float n_in5p3 = 0.00000; + float n_in5p4 = 8.00000; + { + float __input_range = n_in5p2 - n_in5p1; + float __output_range = n_in5p4 - n_in5p3; + n_out5p0 = n_in5p3 + __output_range * ((n_out4p1 - n_in5p1) / __input_range); + } + + +// Texture2D:2 + vec4 n_out2p0 = textureLod(tex_frg_2, UV, n_out5p0); + float n_out2p1 = n_out2p0.r; + + +// Texture2D:3 + vec4 n_out3p0 = texture(tex_frg_3, UV); + float n_out3p1 = n_out3p0.r; + + +// FloatOp:6 + float n_out6p0 = n_out2p1 * n_out3p1; + + +// Input:7 + vec4 n_out7p0 = COLOR; + float n_out7p4 = n_out7p0.a; + + +// FloatOp:8 + float n_out8p0 = n_out6p0 * n_out7p4; + + +// Output:0 + ALPHA = n_out8p0; + + +} +" +graph_offset = Vector2(-547.271, 545.865) +nodes/fragment/0/position = Vector2(400, 900) +nodes/fragment/2/node = SubResource("VisualShaderNodeTexture_mjuxj") +nodes/fragment/2/position = Vector2(-360, 400) +nodes/fragment/3/node = SubResource("VisualShaderNodeTexture_xamyu") +nodes/fragment/3/position = Vector2(-1240, 1020) +nodes/fragment/4/node = SubResource("VisualShaderNodeInput_qilve") +nodes/fragment/4/position = Vector2(-1080, 360) +nodes/fragment/5/node = SubResource("VisualShaderNodeRemap_bocjt") +nodes/fragment/5/position = Vector2(-700, 500) +nodes/fragment/6/node = SubResource("VisualShaderNodeFloatOp_t3qas") +nodes/fragment/6/position = Vector2(-80, 900) +nodes/fragment/7/node = SubResource("VisualShaderNodeInput_586rk") +nodes/fragment/7/position = Vector2(-420, 1240) +nodes/fragment/8/node = SubResource("VisualShaderNodeFloatOp_74lg2") +nodes/fragment/8/position = Vector2(140, 1040) +nodes/fragment/connections = PackedInt32Array(4, 1, 5, 0, 5, 0, 2, 1, 2, 1, 6, 0, 3, 1, 6, 1, 7, 4, 8, 1, 6, 0, 8, 0, 8, 0, 0, 1) diff --git a/game/models/bullet.glb b/game/models/bullet.glb new file mode 100644 index 0000000..8c0131d --- /dev/null +++ b/game/models/bullet.glb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:040e074f3c803efe0301390bd838b1e95fdd963eb1e38fee35d0d264e99f0d91 +size 24104 diff --git a/game/models/bullet.glb.import b/game/models/bullet.glb.import new file mode 100644 index 0000000..defc5c4 --- /dev/null +++ b/game/models/bullet.glb.import @@ -0,0 +1,37 @@ +[remap] + +importer="scene" +importer_version=1 +type="PackedScene" +uid="uid://bg1q0xweaefoq" +path="res://.godot/imported/bullet.glb-761cf96ec3ba072116e1903fca9d773a.scn" + +[deps] + +source_file="res://models/bullet.glb" +dest_files=["res://.godot/imported/bullet.glb-761cf96ec3ba072116e1903fca9d773a.scn"] + +[params] + +nodes/root_type="" +nodes/root_name="" +nodes/apply_root_scale=true +nodes/root_scale=1.0 +nodes/import_as_skeleton_bones=false +nodes/use_node_type_suffixes=true +meshes/ensure_tangents=true +meshes/generate_lods=true +meshes/create_shadow_meshes=true +meshes/light_baking=1 +meshes/lightmap_texel_size=0.2 +meshes/force_disable_compression=false +skins/use_named_skins=true +animation/import=true +animation/fps=30 +animation/trimming=false +animation/remove_immutable_tracks=true +animation/import_rest_as_RESET=false +import_script/path="" +_subresources={} +gltf/naming_version=1 +gltf/embedded_image_handling=1 diff --git a/game/player.tscn b/game/player.tscn index 2279825..70c8eda 100644 --- a/game/player.tscn +++ b/game/player.tscn @@ -209,8 +209,8 @@ process_material = SubResource("ParticleProcessMaterial_dw050") draw_pass_1 = SubResource("PlaneMesh_n7ghd") [node name="RayCast3D" type="RayCast3D" parent="Head/PlayerCamera/pistol"] -transform = Transform3D(0.998255, -0.041771, 0.0417346, 0.041771, -4.37114e-08, -0.999127, 0.0417346, 0.999127, 0.00174477, 0.000758827, 0.0641694, -0.246936) -target_position = Vector3(0, -50, 0) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.000758827, 0.0641694, -0.246936) +target_position = Vector3(0, 0, -90) [node name="OverlayFPS" type="CanvasLayer" parent="Head/PlayerCamera"] script = ExtResource("5_2hs0m")