diff --git a/assets/fonts/Geo/Geo-Italic.ttf.import b/assets/fonts/Geo/Geo-Italic.ttf.import index fb8d294..7070a32 100644 --- a/assets/fonts/Geo/Geo-Italic.ttf.import +++ b/assets/fonts/Geo/Geo-Italic.ttf.import @@ -14,7 +14,7 @@ dest_files=["res://.godot/imported/Geo-Italic.ttf-fff5102e64e08d3e98dbbd3b01b471 Rendering=null antialiasing=1 -generate_mipmaps=false +generate_mipmaps=true disable_embedded_bitmaps=true multichannel_signed_distance_field=false msdf_pixel_range=8 diff --git a/assets/fonts/Geo/Geo-Regular.ttf.import b/assets/fonts/Geo/Geo-Regular.ttf.import index 98a151a..388b779 100644 --- a/assets/fonts/Geo/Geo-Regular.ttf.import +++ b/assets/fonts/Geo/Geo-Regular.ttf.import @@ -14,7 +14,7 @@ dest_files=["res://.godot/imported/Geo-Regular.ttf-ea6aa4330b08d367c3a4134ebd69f Rendering=null antialiasing=1 -generate_mipmaps=false +generate_mipmaps=true disable_embedded_bitmaps=true multichannel_signed_distance_field=false msdf_pixel_range=8 diff --git a/levels/debug_level/debug_level.tscn b/levels/debug_level/debug_level.tscn index f62f429..7561bcb 100644 --- a/levels/debug_level/debug_level.tscn +++ b/levels/debug_level/debug_level.tscn @@ -168,7 +168,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -1.2, 0) shape = SubResource("BoxShape3D_x3wvm") [node name="ShotSetup" parent="." instance=ExtResource("8_h44v5")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 218.499, 4, 294.341) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 212.717, 4, 294.073) [node name="Buildings" type="Node3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 129.404, -9.53674e-07, 309.4) diff --git a/levels/debug_level/terrain_3d_storage.res b/levels/debug_level/terrain_3d_storage.res index 1c432c8..fb19a74 100644 --- a/levels/debug_level/terrain_3d_storage.res +++ b/levels/debug_level/terrain_3d_storage.res @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a04fe09af8b7814448360b039ab9fe5661b0b1df2c142a460cfefb80b2045bf3 -size 656651 +oid sha256:15963516f2fa043cc75864de02faf0c77215491bbd49f5b0d57624b070f199f9 +size 740017 diff --git a/src/characters/gfolf_girl/gfolf_girl.tscn b/src/characters/gfolf_girl/gfolf_girl.tscn index 2fe4d13..eaa2c0f 100644 --- a/src/characters/gfolf_girl/gfolf_girl.tscn +++ b/src/characters/gfolf_girl/gfolf_girl.tscn @@ -169,7 +169,7 @@ bones/23/scale = Vector3(1, 1, 1) visible = false [node name="BoneAttachment3D" type="BoneAttachment3D" parent="Armature/Skeleton3D" index="6"] -transform = Transform3D(-0.944824, 0.316851, -0.0831416, -0.326581, -0.930889, 0.163676, -0.0255346, 0.181798, 0.983005, -0.1687, 3.14336, 0.866657) +transform = Transform3D(-0.944824, 0.316851, -0.0831417, -0.326595, -0.930784, 0.164246, -0.0253454, 0.182337, 0.982909, -0.1687, 3.13128, 0.867055) bone_name = "Hand.R" bone_idx = 11 diff --git a/src/player/free_camera/free_camera.tscn b/src/player/free_camera/free_camera.tscn index b65d197..be04cd7 100644 --- a/src/player/free_camera/free_camera.tscn +++ b/src/player/free_camera/free_camera.tscn @@ -5,6 +5,7 @@ [sub_resource type="SphereShape3D" id="SphereShape3D_wmusx"] [node name="FreeCamera" type="CharacterBody3D"] +process_mode = 3 collision_layer = 0 script = ExtResource("1_3gm3q") diff --git a/src/player/shot_setup/shot_setup.gd b/src/player/shot_setup/shot_setup.gd index 876d5ba..5852268 100644 --- a/src/player/shot_setup/shot_setup.gd +++ b/src/player/shot_setup/shot_setup.gd @@ -34,6 +34,9 @@ const CAMERA_SNAP_TIME := 0.3 @export var base_power := 2.5 @export var base_curve := 0.0 +@export_category("Debug") +@export var debug_ball_impact := false + var base_speed: float = ProjectSettings.get_setting("game/config/controls/camera/free_camera_speed") var x_sensitivity: float = ProjectSettings.get_setting( @@ -85,7 +88,9 @@ var _tracking_camera: OrbitalCamera @onready var shot_animation: AnimationPlayer = %ShotAnimation @onready var arrow: Node3D = %Arrow +@onready var arrow_pivot: Node3D = %ArrowPivot @onready var arrow_animation: AnimationPlayer = %ArrowAnimation +@onready var shot_projection: ProjectileArc = %ShotProjection @onready var power_bar: ProgressBar = %PowerBar @onready var power_animation: AnimationPlayer = %PowerAnimation @@ -160,24 +165,42 @@ func finish_downswing() -> void: phase = Phase.SHOT +func get_shot_impulse(meter_pct: float) -> Vector3: + return -shot_ref.global_basis.z * base_power * meter_pct + + func take_shot() -> void: print("WHACK!") print("Power: ", power_bar.value) print("Curve: ", curve_bar.value) - var impulse := shot_ref.global_basis.z * base_power * power_bar.value - print("Shot impulse: ", impulse) + var impulse := get_shot_impulse(power_bar.value) + print("Shot impulse: ", impulse, "; ", impulse.length(), " N*s") ball_impulse_debug.transform = ( Transform3D.IDENTITY.scaled(Vector3.ONE * impulse.length()).looking_at(impulse) ) physics_ball.freeze = false - physics_ball.apply_central_impulse(impulse) + #physics_ball.apply_central_impulse(impulse) + physics_ball.apply_impulse(impulse) + + +## Make the shot projection widget visible, with animated transition +func _show_shot_projection() -> void: + shot_projection.initial_speed = 1 + shot_projection.basis = shot_ref.basis + var shot_speed := get_shot_impulse(1.0).length() / physics_ball.mass + var tween := get_tree().create_tween() + tween.tween_property(shot_projection, "initial_speed", shot_speed, CAMERA_SNAP_TIME).set_trans( + Tween.TRANS_QUAD + ) + shot_projection.show() func insert_free_cam() -> void: arrow_animation.play("hide") + _show_shot_projection() hud_state.travel("hidden") _free_camera = FreeCamera.create(camera) add_sibling(_free_camera) @@ -188,6 +211,7 @@ func insert_free_cam() -> void: func return_free_cam() -> void: # TODO alter shot aim based on free camera selection arrow_animation.play("show") + shot_projection.hide() hud_state.travel("visible") _free_camera.queue_free() _free_camera = null @@ -322,7 +346,9 @@ func _process(delta: float) -> void: pitch.rotation.x = lerp_angle(pitch.rotation.x, _target_rotation.x, delta * y_acceleration) # Arrow lags behind camera control - arrow.rotation.y = lerp_angle(arrow.rotation.y, _target_rotation.y, delta * ARROW_ACCELERATION) + arrow_pivot.rotation.y = lerp_angle( + arrow_pivot.rotation.y, _target_rotation.y, delta * ARROW_ACCELERATION + ) # Player lags further behind player_pivot.rotation.y = lerp_angle( player_pivot.rotation.y, _target_rotation.y, delta * PLAYER_ACCELERATION @@ -414,6 +440,17 @@ func _on_physics_ball_sleeping_state_changed() -> void: func _on_ball_entered_water() -> void: # Should only be possible during SHOT phase, but let's check just to be sure... if phase == Phase.SHOT: - print("INTO THE DRINK!!") physics_ball.freeze = true wasted_animation.play("display") + + +func _on_physics_ball_body_entered(_body: Node) -> void: + print_debug("BONK!") + if debug_ball_impact: + get_tree().paused = true + _free_camera = FreeCamera.create( + (_tracking_camera if _tracking_camera else camera) as Node3D + ) + add_sibling(_free_camera) + control_disabled = true + camera.current = false diff --git a/src/player/shot_setup/shot_setup.tscn b/src/player/shot_setup/shot_setup.tscn index a49b875..3d9f516 100644 --- a/src/player/shot_setup/shot_setup.tscn +++ b/src/player/shot_setup/shot_setup.tscn @@ -1,10 +1,12 @@ -[gd_scene load_steps=38 format=3 uid="uid://cy7t2tc4y3b4"] +[gd_scene load_steps=40 format=3 uid="uid://cy7t2tc4y3b4"] [ext_resource type="Script" path="res://src/player/shot_setup/shot_setup.gd" id="1_r6ei4"] [ext_resource type="PackedScene" uid="uid://dfttci386ohip" path="res://src/player/physics_ball/physics_ball.tscn" id="2_1i5j5"] -[ext_resource type="PackedScene" uid="uid://c2k88ns0h5ie1" path="res://src/ui/arrow.tscn" id="2_s70wl"] +[ext_resource type="PackedScene" uid="uid://c2k88ns0h5ie1" path="res://src/ui/arrow/arrow.tscn" id="2_s70wl"] [ext_resource type="PackedScene" uid="uid://1s3gywmoi20e" path="res://src/characters/gfolf_girl/gfolf_girl.tscn" id="3_e4aur"] [ext_resource type="PackedScene" uid="uid://445qd7m4qe2j" path="res://src/player/shot_setup/club_selector/club_selector.tscn" id="4_56ape"] +[ext_resource type="PackedScene" uid="uid://fht6j87o8ecr" path="res://src/ui/projectile_arc/projectile_arc.tscn" id="4_ry2ho"] +[ext_resource type="PackedScene" uid="uid://dbdul15c4oblg" path="res://src/ui/projected_target.tscn" id="6_mynqj"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_lnol1"] albedo_color = Color(0, 0.537255, 1, 1) @@ -639,6 +641,8 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.08, 0) unique_name_in_owner = true transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 0, 0, 0) freeze = true +contact_monitor = true +max_contacts_reported = 1 [node name="BallImpulseDebug" type="Node3D" parent="BallPoint"] unique_name_in_owner = true @@ -660,27 +664,27 @@ unique_name_in_owner = true [node name="DriveRef" type="RayCast3D" parent="Direction"] unique_name_in_owner = true -transform = Transform3D(-1, 6.18172e-08, -6.18172e-08, 0, 0.707107, 0.707107, 8.74228e-08, 0.707107, -0.707107, 0, 0.08, 0) +transform = Transform3D(1, 0, 0, 0, 0.707107, -0.707107, 0, 0.707107, 0.707107, 0, 0.08, 0) enabled = false -target_position = Vector3(0, 0, 1) +target_position = Vector3(0, 0, -1) collision_mask = 0 collide_with_bodies = false debug_shape_thickness = 4 [node name="WedgeRef" type="RayCast3D" parent="Direction"] unique_name_in_owner = true -transform = Transform3D(-0.7, -5.29972e-08, 3.0598e-08, 0, 0.35, 0.606218, -6.11959e-08, 0.606218, -0.35, 0, 0.08, 0) +transform = Transform3D(0.7, 0, 0, 0, 0.35, -0.606218, 0, 0.606218, 0.35, 0, 0.08, 0) enabled = false -target_position = Vector3(0, 0, 1) +target_position = Vector3(0, 0, -1) collision_mask = 0 collide_with_bodies = false debug_shape_thickness = 4 [node name="PuttRef" type="RayCast3D" parent="Direction"] unique_name_in_owner = true -transform = Transform3D(-1, 0, -1.50996e-07, 0, 1, 0, 1.50996e-07, 0, -1, 0, 0.08, 0) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.08, 0) enabled = false -target_position = Vector3(0, 0, 1) +target_position = Vector3(0, 0, -1) collision_mask = 0 collide_with_bodies = false debug_shape_thickness = 4 @@ -702,35 +706,50 @@ unique_name_in_owner = true transform = Transform3D(1, 0, 0, 0, 1, 2.98023e-08, 0, -2.98023e-08, 1, 0, 0, 0) current = true -[node name="Arrow" type="Node3D" parent="."] +[node name="ArrowPivot" type="Node3D" parent="."] unique_name_in_owner = true -transform = Transform3D(0.001, 0, 0, 0, 0.001, 0, 0, 0, 0.001, 0, 0.1, 0) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.1, 0) -[node name="ArrowAnimation" type="AnimationPlayer" parent="Arrow"] +[node name="Arrow" type="Node3D" parent="ArrowPivot"] +unique_name_in_owner = true +transform = Transform3D(0.001, 0, 0, 0, 0.001, 0, 0, 0, 0.001, 0, 0, 0) + +[node name="ArrowAnimation" type="AnimationPlayer" parent="ArrowPivot/Arrow"] unique_name_in_owner = true libraries = { "": SubResource("AnimationLibrary_rw0cf") } autoplay = "show" -[node name="DriveArrow" type="Node3D" parent="Arrow"] +[node name="DriveArrow" type="Node3D" parent="ArrowPivot/Arrow"] unique_name_in_owner = true transform = Transform3D(1, 0, 0, 0, 0.707107, 0.707107, 0, -0.707107, 0.707107, 0, 0, 0) visible = false -[node name="ArrowMesh" parent="Arrow/DriveArrow" instance=ExtResource("2_s70wl")] +[node name="ArrowMesh" parent="ArrowPivot/Arrow/DriveArrow" instance=ExtResource("2_s70wl")] transform = Transform3D(0.2, 0, 0, 0, 0.4, 0, 0, 0, 0.2, 0, 1, 0) loop_animation = 1 -[node name="PuttArrow" type="Node3D" parent="Arrow"] +[node name="PuttArrow" type="Node3D" parent="ArrowPivot/Arrow"] unique_name_in_owner = true transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, 0) visible = false -[node name="ArrowMesh" parent="Arrow/PuttArrow" instance=ExtResource("2_s70wl")] +[node name="ArrowMesh" parent="ArrowPivot/Arrow/PuttArrow" instance=ExtResource("2_s70wl")] transform = Transform3D(0.2, 0, 0, 0, 0.4, 0, 0, 0, 0.2, 0, 1, 0) loop_animation = 1 +[node name="ShotProjection" parent="ArrowPivot" node_paths=PackedStringArray("excluded_bodies") instance=ExtResource("4_ry2ho")] +unique_name_in_owner = true +transform = Transform3D(1, 0, 0, 0, 0.707107, -0.707107, 0, 0.707107, 0.707107, 0, -0.02, 0) +visible = false +initial_speed = 50.0 +time_step = 0.01 +max_steps = 800 +excluded_bodies = [NodePath("../../BallPoint/PhysicsBall")] + +[node name="ProjectedTarget" parent="ArrowPivot/ShotProjection" instance=ExtResource("6_mynqj")] + [node name="ShotAnimation" type="AnimationPlayer" parent="."] unique_name_in_owner = true root_node = NodePath("../Direction/Elevation/Pitch/Zoom/Camera") @@ -908,5 +927,6 @@ root_node = NodePath("%HUDStateMachine/..") tree_root = SubResource("AnimationNodeStateMachine_osrbp") anim_player = NodePath("../HUDAnimation") +[connection signal="body_entered" from="BallPoint/PhysicsBall" to="." method="_on_physics_ball_body_entered"] [connection signal="entered_water" from="BallPoint/PhysicsBall" to="." method="_on_ball_entered_water"] [connection signal="sleeping_state_changed" from="BallPoint/PhysicsBall" to="." method="_on_physics_ball_sleeping_state_changed"] diff --git a/src/shaders/hologram.gdshader b/src/shaders/hologram.gdshader new file mode 100644 index 0000000..99e709c --- /dev/null +++ b/src/shaders/hologram.gdshader @@ -0,0 +1,47 @@ +// Hologram shader +// Adapted from https://godotshaders.com/shader/scifi-hologram/ + +shader_type spatial; +render_mode unshaded; + +uniform sampler2D texture_image; + +uniform mediump vec4 line_color : source_color = vec4(0.0, 1.0, 0.0, 1.0); +uniform mediump float line_width : hint_range(0, 1) = 0.005; +uniform mediump float line_blur : hint_range(0, 1) = 0.2; +uniform mediump float line_speed : hint_range(-1, 1) = 0.02; +uniform bool straight_lines = true; + +uniform mediump float interrupt_width : hint_range(0, 1) = 0.5; +uniform mediump float interrupt_blur : hint_range(0, 1) = 0.25; +uniform mediump float interrupt_speed : hint_range(-1, 1) = 0.2; + +uniform mediump vec4 glow_color : source_color = vec4(0.5, 0.75, 1.0, 1.0); +uniform lowp float glow_itensity : hint_range(0, 20) = 4.5; +uniform lowp float glow_amount : hint_range(0, 20) = 4.5; +uniform lowp float flickering : hint_range(0, 1) = 0.55; + +vec3 fresnel_glow(float amount, float intensity, vec3 color, vec3 normal, vec3 view) { + return pow((1.0 - dot(normalize(normal), normalize(view))), amount) * color * intensity; +} + +void fragment () { + vec2 canvas; + if (straight_lines) { + canvas = SCREEN_UV; + } else { + canvas = vec2(VIEW.x, VIEW.y); + } + vec2 lines = vec2(clamp(sin((TIME * line_speed + canvas.y) / line_width), line_blur, 1.0 - line_blur), canvas.x); + vec2 interupts = vec2(clamp(sin((TIME * interrupt_speed + canvas.y) / interrupt_width * 3.0), interrupt_blur, 1.0 - interrupt_blur), canvas.x); + + float flicker = clamp(fract(cos(TIME) * 43758.5453123), flickering, 1.0); + vec4 imgtex = flicker * line_color * texture(texture_image, lines * interupts); + vec3 imgtex_color = vec3(imgtex.r, imgtex.g, imgtex.b); + vec3 fresnel_color = vec3(glow_color.r, glow_color.g, glow_color.b); + vec3 fresnel = fresnel_glow(glow_amount, glow_itensity, fresnel_color, NORMAL, VIEW); + ALBEDO = imgtex_color + fresnel; + + EMISSION = glow_amount * vec3(glow_color.r, glow_color.g, glow_color.b); + ALPHA = lines.x * interupts.x; +} \ No newline at end of file diff --git a/src/shaders/plasma.gdshader b/src/shaders/plasma.gdshader new file mode 100644 index 0000000..c9debb4 --- /dev/null +++ b/src/shaders/plasma.gdshader @@ -0,0 +1,41 @@ +// Plasma Pulse shader +// Adapted from https://godotshaders.com/shader/scifi-hologram/ + +shader_type spatial; +render_mode unshaded, cull_back; + +uniform mediump vec3 albedo: source_color = vec3(0.9, 0.0, 0.7); + +uniform bool transpose_axis = false; + +uniform mediump sampler2D wave_gradient; +uniform mediump float wave_width: hint_range(0, 10) = 1; +uniform mediump float wave_speed: hint_range(-1, 1) = 0.4; + +uniform mediump vec4 glow_color: source_color = vec4(0.5, 0.75, 1.0, 1.0); +uniform lowp float glow_intensity: hint_range(0, 20) = 0.618; +uniform lowp float glow_amount: hint_range(0, 20) = 4.5; + +uniform mediump sampler2D pulse_gradient; +uniform mediump float pulse_speed: hint_range(0, 10) = 0.3; + +vec3 fresnel_glow(float amount, float intensity, vec3 color, vec3 normal, vec3 view) { + return pow((1.0 - dot(normalize(normal), normalize(view))), amount) * color * intensity; +} + +void fragment () { + float canvas = -UV.x; + if(transpose_axis) { + canvas = -UV.y; + } + float wave_value = texture(wave_gradient, vec2((canvas + TIME * wave_speed) / wave_width, 0)).r; + + vec3 fresnel_color = vec3(glow_color.r, glow_color.g, glow_color.b); + vec3 fresnel = fresnel_glow(glow_amount, glow_intensity, fresnel_color, NORMAL, VIEW); + + float pulse_value = texture(pulse_gradient, vec2(TIME * pulse_speed, 0)).r; + + ALBEDO = albedo + fresnel; + EMISSION = glow_amount * vec3(glow_color.r, glow_color.g, glow_color.b); + ALPHA = wave_value * pulse_value; +} \ No newline at end of file diff --git a/src/ui/arrow.gd b/src/ui/arrow/arrow.gd similarity index 100% rename from src/ui/arrow.gd rename to src/ui/arrow/arrow.gd diff --git a/src/ui/arrow.tscn b/src/ui/arrow/arrow.tscn similarity index 97% rename from src/ui/arrow.tscn rename to src/ui/arrow/arrow.tscn index 695845f..e3cc4fc 100644 --- a/src/ui/arrow.tscn +++ b/src/ui/arrow/arrow.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=9 format=3 uid="uid://c2k88ns0h5ie1"] [ext_resource type="PackedScene" uid="uid://bw54bi35myvpg" path="res://assets/models/ui/arrow/arrow.glb" id="1_xifl6"] -[ext_resource type="Script" path="res://src/ui/arrow.gd" id="2_0viam"] +[ext_resource type="Script" path="res://src/ui/arrow/arrow.gd" id="2_0viam"] [ext_resource type="Material" uid="uid://d3ka0yjhxu5ks" path="res://assets/materials/gummy_material.tres" id="3_g7vwe"] [sub_resource type="Animation" id="Animation_hsqkd"] diff --git a/src/ui/projected_target.tscn b/src/ui/projected_target.tscn new file mode 100644 index 0000000..55be44c --- /dev/null +++ b/src/ui/projected_target.tscn @@ -0,0 +1,117 @@ +[gd_scene load_steps=10 format=3 uid="uid://dbdul15c4oblg"] + +[ext_resource type="Shader" path="res://src/shaders/plasma.gdshader" id="1_nf38g"] +[ext_resource type="FontFile" uid="uid://b6gxwgomstkgu" path="res://assets/fonts/Geo/Geo-Italic.ttf" id="2_ckdn3"] + +[sub_resource type="Gradient" id="Gradient_3oor7"] +interpolation_mode = 2 +offsets = PackedFloat32Array(0, 0.5, 1) +colors = PackedColorArray(1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1) + +[sub_resource type="GradientTexture1D" id="GradientTexture1D_ic835"] +gradient = SubResource("Gradient_3oor7") + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_msl6u"] +render_priority = 0 +shader = ExtResource("1_nf38g") +shader_parameter/albedo = Color(1, 0.19, 0.2035, 1) +shader_parameter/transpose_axis = true +shader_parameter/wave_width = 0.4 +shader_parameter/wave_speed = -0.3 +shader_parameter/glow_color = Color(0.5, 0.75, 1, 1) +shader_parameter/glow_intensity = 0.618 +shader_parameter/glow_amount = 4.5 +shader_parameter/pulse_speed = 0.3 +shader_parameter/wave_gradient = SubResource("GradientTexture1D_ic835") + +[sub_resource type="SphereMesh" id="SphereMesh_dbo5p"] +material = SubResource("ShaderMaterial_msl6u") +radial_segments = 16 +rings = 16 + +[sub_resource type="Animation" id="Animation_npp1f"] +resource_name = "rotate" +length = 3.236 +loop_mode = 1 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:rotation") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 3.236), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [Vector3(0, 0, 0), Vector3(0, -3.14159, 0)] +} + +[sub_resource type="Animation" id="Animation_yu68k"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:rotation") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [Vector3(0, 0, 0)] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_vm52d"] +_data = { +"RESET": SubResource("Animation_yu68k"), +"rotate": SubResource("Animation_npp1f") +} + +[node name="ProjectedTarget" type="MeshInstance3D"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0) +mesh = SubResource("SphereMesh_dbo5p") + +[node name="Pivot" type="Node3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.02, 0) + +[node name="Label3D" type="Label3D" parent="Pivot"] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, 1, 0, -1, -4.37114e-08, 0, 0, 0.55) +pixel_size = 0.001 +texture_filter = 5 +modulate = Color(1, 0.188235, 0.203922, 1) +text = "DANGER" +font = ExtResource("2_ckdn3") +font_size = 64 + +[node name="Label3D2" type="Label3D" parent="Pivot"] +transform = Transform3D(-1, 8.74228e-08, 3.82137e-15, 0, -4.37114e-08, 1, 8.74228e-08, 1, 4.37114e-08, 0, 0, -0.55) +pixel_size = 0.001 +texture_filter = 5 +modulate = Color(1, 0.188235, 0.203922, 1) +text = "DANGER" +font = ExtResource("2_ckdn3") +font_size = 64 + +[node name="Label3D3" type="Label3D" parent="Pivot"] +transform = Transform3D(-4.37114e-08, -1, -4.37114e-08, 0, -4.37114e-08, 1, -1, 4.37114e-08, 1.91069e-15, 0.55, 0, 0) +pixel_size = 0.001 +texture_filter = 5 +modulate = Color(1, 0.188235, 0.203922, 1) +text = "DANGER" +font = ExtResource("2_ckdn3") +font_size = 64 + +[node name="Label3D4" type="Label3D" parent="Pivot"] +transform = Transform3D(-4.37114e-08, 1, 4.37114e-08, 0, -4.37114e-08, 1, 1, 4.37114e-08, 1.91069e-15, -0.55, 0, 0) +pixel_size = 0.001 +texture_filter = 5 +modulate = Color(1, 0.188235, 0.203922, 1) +text = "DANGER" +font = ExtResource("2_ckdn3") +font_size = 64 + +[node name="AnimationPlayer" type="AnimationPlayer" parent="Pivot"] +libraries = { +"": SubResource("AnimationLibrary_vm52d") +} +autoplay = "rotate" diff --git a/src/ui/projectile_arc/projectile_arc.gd b/src/ui/projectile_arc/projectile_arc.gd new file mode 100644 index 0000000..8e5d8e0 --- /dev/null +++ b/src/ui/projectile_arc/projectile_arc.gd @@ -0,0 +1,95 @@ +class_name ProjectileArc extends Node3D +## Visually project the arc of a projectile through space. +## +## If this node has any children, they will be positioned wherever the projection ends. + +## Initial speed of the projectile, in m/s. +## The projectile's initial direction vector is the negative Z direction relative to this node. +@export var initial_speed := 1.0 + +@export_category("Projection") +## Time between projection steps, in seconds. +@export var time_step := 0.2 +## Maximum number of steps to predict before stopping. +@export var max_steps := 50 +## Ticks between each projection update. 0 means update every tick. +@export var ticks_per_update := 0 + +@export_category("Collision") +## Enables collision checking. Projection will end at the point where a collision is detected. +## Uses continuous collision detection. +@export var check_collision := true +## Mask for collision checking. +@export_flags_3d_physics var collision_mask := 1 +## Bodies excluded from collision checking. +## This should probably include the ball! +@export var excluded_bodies: Array[CollisionObject3D] = [] + +var _tick_counter := 0 + +@onready var polygon: CSGPolygon3D = %Polygon +@onready var path: Path3D = %Path + +@onready var gravity: float = ProjectSettings.get_setting("physics/3d/default_gravity") +@onready var gravity_vec: Vector3 = ProjectSettings.get_setting("physics/3d/default_gravity_vector") + + +func _process(_delta: float) -> void: + if not visible: + # Don't bother if we're not visible + return + + # Short-circuit if we need to wait more ticks + if _tick_counter > 0: + _tick_counter -= 1 + return + _tick_counter = ticks_per_update + + # Rebuild path curve + path.global_basis = Basis.IDENTITY + path.curve.clear_points() + + var space := get_world_3d().direct_space_state + var excluded_rid: Array[RID] = [] + excluded_rid.assign(excluded_bodies.map(func(k: CollisionObject3D) -> RID: return k.get_rid())) + + var pos := global_position + var vel := -global_basis.z * initial_speed + + for t in range(0, max_steps): + # TODO: smooth curve with bezier handles + path.curve.add_point(pos - global_position) + + # Integrate projectile path + vel += gravity * gravity_vec * time_step + var next_pos := pos + vel * time_step + + # Collision + if check_collision: + var ray_params := PhysicsRayQueryParameters3D.create( + pos, next_pos, collision_mask, excluded_rid + ) + var collision := space.intersect_ray(ray_params) + if collision: + # Set current position to collision point, so it will be added to the path + # TODO: we could project further using the surface normal here... + pos = collision["position"] + # End projection! + break + + pos = next_pos + + # Add terminal point (possibly collision point) + path.curve.add_point(pos - global_position) + + # Reposition any children + for n: Node in get_children(): + if n is Node3D and n != path: + var node_3d: Node3D = n + node_3d.global_position = pos + node_3d.global_basis = Basis.IDENTITY + + +func _on_visibility_changed() -> void: + # Force update as soon as visible + _tick_counter = 0 diff --git a/src/ui/projectile_arc/projectile_arc.tscn b/src/ui/projectile_arc/projectile_arc.tscn new file mode 100644 index 0000000..0821265 --- /dev/null +++ b/src/ui/projectile_arc/projectile_arc.tscn @@ -0,0 +1,59 @@ +[gd_scene load_steps=9 format=3 uid="uid://fht6j87o8ecr"] + +[ext_resource type="Script" path="res://src/ui/projectile_arc/projectile_arc.gd" id="1_vafqi"] +[ext_resource type="Shader" path="res://src/shaders/plasma.gdshader" id="2_pi36v"] + +[sub_resource type="Curve3D" id="Curve3D_rfv3d"] + +[sub_resource type="Gradient" id="Gradient_28hbf"] +offsets = PackedFloat32Array(0, 0.37193, 0.838596, 1) +colors = PackedColorArray(0.197937, 0.197937, 0.197937, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0.197937, 0.197937, 0.197937, 1) + +[sub_resource type="GradientTexture1D" id="GradientTexture1D_8xhfy"] +gradient = SubResource("Gradient_28hbf") + +[sub_resource type="Gradient" id="Gradient_yx8sm"] +interpolation_mode = 2 +offsets = PackedFloat32Array(0.0666667, 0.287719, 1) +colors = PackedColorArray(1, 1, 1, 1, 0.485904, 0.485904, 0.485904, 1, 0, 0, 0, 1) + +[sub_resource type="GradientTexture1D" id="GradientTexture1D_l8ond"] +gradient = SubResource("Gradient_yx8sm") + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_ahf42"] +render_priority = 0 +shader = ExtResource("2_pi36v") +shader_parameter/albedo = Color(0.9, 0, 0.7, 1) +shader_parameter/transpose_axis = false +shader_parameter/wave_width = 2.0 +shader_parameter/wave_speed = 0.6 +shader_parameter/glow_color = Color(0.5, 0.75, 1, 1) +shader_parameter/glow_intensity = 0.618 +shader_parameter/glow_amount = 4.5 +shader_parameter/pulse_speed = 0.3 +shader_parameter/wave_gradient = SubResource("GradientTexture1D_l8ond") +shader_parameter/pulse_gradient = SubResource("GradientTexture1D_8xhfy") + +[node name="ProjectileArc" type="Node3D"] +script = ExtResource("1_vafqi") + +[node name="Path" type="Path3D" parent="."] +unique_name_in_owner = true +curve = SubResource("Curve3D_rfv3d") + +[node name="Polygon" type="CSGPolygon3D" parent="Path"] +unique_name_in_owner = true +polygon = PackedVector2Array(0, -0.1, -0.2, 0, 0, 0.1, 0.2, 0) +mode = 2 +path_node = NodePath("..") +path_interval_type = 0 +path_interval = 1.0 +path_simplify_angle = 0.0 +path_rotation = 2 +path_local = true +path_continuous_u = true +path_u_distance = 1.0 +path_joined = false +material = SubResource("ShaderMaterial_ahf42") + +[connection signal="visibility_changed" from="." to="." method="_on_visibility_changed"] diff --git a/src/world/ball_zone/ball_zone.gd b/src/world/ball_zone/ball_zone.gd index e75df8e..3efa4f0 100644 --- a/src/world/ball_zone/ball_zone.gd +++ b/src/world/ball_zone/ball_zone.gd @@ -14,12 +14,11 @@ func on_ball_entered(ball: GameBall) -> void: ball.entered_water.emit() -func on_ball_exited(ball: GameBall) -> void: +func on_ball_exited(_ball: GameBall) -> void: pass func _on_body_entered(body: Node3D) -> void: - print("BODY ENTERED ZONE: ", body) if body is GameBall: on_ball_entered(body as GameBall)