From 2db529b34a0efc468015aa7ca869e32188b35c2f Mon Sep 17 00:00:00 2001 From: Rob Kelly Date: Mon, 11 Nov 2024 11:39:12 -0700 Subject: [PATCH] Water hazards --- levels/debug_level/debug_level.tscn | 16 +- src/player/physics_ball/game_ball.gd | 4 + src/player/physics_ball/physics_ball.tscn | 5 +- src/player/shot_setup/shot_setup.gd | 32 ++-- src/player/shot_setup/shot_setup.tscn | 188 +++++++++++++++++++++- src/world/ball_zone/ball_zone.gd | 29 ++++ 6 files changed, 256 insertions(+), 18 deletions(-) create mode 100644 src/player/physics_ball/game_ball.gd create mode 100644 src/world/ball_zone/ball_zone.gd diff --git a/levels/debug_level/debug_level.tscn b/levels/debug_level/debug_level.tscn index 495ade3..beeea4c 100644 --- a/levels/debug_level/debug_level.tscn +++ b/levels/debug_level/debug_level.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=34 format=3 uid="uid://bm2o3mex10v11"] +[gd_scene load_steps=36 format=3 uid="uid://bm2o3mex10v11"] [ext_resource type="Terrain3DStorage" uid="uid://bu1gewgsgc5hm" path="res://levels/debug_level/terrain_3d_storage.res" id="1_nlsu2"] [ext_resource type="Texture2D" path="res://assets/textures/grass_fairway/grass_fairway_albedo.dds" id="2_e4m27"] @@ -9,6 +9,7 @@ [ext_resource type="Texture2D" uid="uid://c47ern0l2d50r" path="res://assets/vista_2.png" id="6_ectru"] [ext_resource type="Texture2D" uid="uid://con5a36t6n6sq" path="res://assets/textures/clear_sea_water_2048x2048.png" id="7_t86h2"] [ext_resource type="PackedScene" uid="uid://cy7t2tc4y3b4" path="res://src/player/shot_setup/shot_setup.tscn" id="8_h44v5"] +[ext_resource type="Script" path="res://src/world/ball_zone/ball_zone.gd" id="9_jwlau"] [ext_resource type="PackedScene" uid="uid://dagh38vap4t1d" path="res://src/scenery/city/concrete_building_1.tscn" id="10_lf15j"] [ext_resource type="PackedScene" uid="uid://cjubxs7peir5k" path="res://src/scenery/city/kana_signboard.tscn" id="11_evxup"] [ext_resource type="PackedScene" uid="uid://di7aql54lksn7" path="res://src/scenery/trees/palm_tree/palm_tree.tscn" id="12_sswxf"] @@ -126,6 +127,9 @@ size = Vector2(4096, 4096) subdivide_width = 256 subdivide_depth = 256 +[sub_resource type="BoxShape3D" id="BoxShape3D_x3wvm"] +size = Vector3(4096, 2, 4096) + [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_5p7vs"] albedo_texture = ExtResource("14_y7s2h") uv1_scale = Vector3(300, 800, 1) @@ -151,10 +155,18 @@ camera_attributes = SubResource("CameraAttributesPractical_ypy22") [node name="DirectionalLight3D" type="DirectionalLight3D" parent="."] transform = Transform3D(1, 0, 0, 0, 0.29404, 0.955793, 0, -0.955793, 0.29404, 0, 0, 0) -[node name="WaterTable2" type="MeshInstance3D" parent="."] +[node name="WaterTable" type="MeshInstance3D" parent="."] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -2, 0) mesh = SubResource("PlaneMesh_2ywhk") +[node name="BallZone" type="Area3D" parent="WaterTable"] +script = ExtResource("9_jwlau") +water_hazard = true + +[node name="CollisionShape3D" type="CollisionShape3D" parent="WaterTable/BallZone"] +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) diff --git a/src/player/physics_ball/game_ball.gd b/src/player/physics_ball/game_ball.gd new file mode 100644 index 0000000..61cb49f --- /dev/null +++ b/src/player/physics_ball/game_ball.gd @@ -0,0 +1,4 @@ +class_name GameBall extends RigidBody3D +## Base class for all gfolf balls + +signal entered_water diff --git a/src/player/physics_ball/physics_ball.tscn b/src/player/physics_ball/physics_ball.tscn index 5f2b5d7..a7beb42 100644 --- a/src/player/physics_ball/physics_ball.tscn +++ b/src/player/physics_ball/physics_ball.tscn @@ -1,5 +1,6 @@ -[gd_scene load_steps=7 format=3 uid="uid://dfttci386ohip"] +[gd_scene load_steps=8 format=3 uid="uid://dfttci386ohip"] +[ext_resource type="Script" path="res://src/player/physics_ball/game_ball.gd" id="1_iwh2u"] [ext_resource type="Texture2D" uid="uid://ckhiq6rfjv63u" path="res://assets/textures/gfolfball/gfolfball.png" id="1_y3q5j"] [ext_resource type="Texture2D" uid="uid://btntjs7mbdigu" path="res://assets/textures/gfolfball/gfolfball_normal.png" id="2_mx7l6"] @@ -30,11 +31,11 @@ rings = 6 radius = 0.05 [node name="PhysicsBall" type="RigidBody3D"] -collision_layer = 0 mass = 0.05 physics_material_override = SubResource("PhysicsMaterial_2gatw") continuous_cd = true linear_damp_mode = 1 +script = ExtResource("1_iwh2u") [node name="BallMesh" type="MeshInstance3D" parent="."] mesh = SubResource("SphereMesh_y0d13") diff --git a/src/player/shot_setup/shot_setup.gd b/src/player/shot_setup/shot_setup.gd index af0a482..eafa553 100644 --- a/src/player/shot_setup/shot_setup.gd +++ b/src/player/shot_setup/shot_setup.gd @@ -67,6 +67,8 @@ var shot_ref: Node3D var _free_camera: FreeCamera var _returning_free_camera := false +var _tracking_camera: OrbitalCamera + @onready var direction: Node3D = %Direction @onready var elevation: Node3D = %Elevation @onready var pitch: Node3D = %Pitch @@ -98,6 +100,7 @@ var _returning_free_camera := false @onready var club_selector: ClubSelector = %ClubSelector @onready var nice_animation: AnimationPlayer = %NiceAnimation +@onready var wasted_animation: AnimationPlayer = %WastedAnimation @onready var hud_state_machine: AnimationTree = %HUDStateMachine @onready var hud_state: AnimationNodeStateMachinePlayback = hud_state_machine["parameters/playback"] @@ -189,9 +192,8 @@ func return_free_cam() -> void: func return_ball() -> void: - var tween := get_tree().create_tween() - physics_ball.freeze = true + var tween := get_tree().create_tween() ( tween . tween_property( @@ -202,6 +204,7 @@ func return_ball() -> void: ) . set_trans(Tween.TRANS_SINE) ) + tween.tween_callback(end_shot_track) func travel_to_ball() -> void: @@ -211,17 +214,19 @@ func travel_to_ball() -> void: func start_shot_track() -> void: - #tracking_camera.make_current() - #tracking_camera.active = true if phase == Phase.SHOT: - var orbital_cam := OrbitalCamera.create(physics_ball) - orbital_cam.rotation.y = randf_range(0.0, TAU) - add_sibling(orbital_cam) + _tracking_camera = OrbitalCamera.create(physics_ball) + _tracking_camera.rotation.y = randf_range(0.0, TAU) + add_sibling(_tracking_camera) + _tracking_camera.global_transform = ball_point.global_transform func end_shot_track() -> void: camera.make_current() - #tracking_camera.active = false + if is_instance_valid(_tracking_camera): + _tracking_camera.queue_free() + if phase == Phase.SHOT: + phase = Phase.FINISHED ## Called immediately before `club` is mutated. @@ -278,7 +283,6 @@ func _on_phase_change(new_phase: Phase) -> void: Phase.FINISHED: power_bar.hide() curve_bar.hide() - end_shot_track() travel_to_ball() @@ -377,4 +381,12 @@ func _process(delta: float) -> void: func _on_physics_ball_sleeping_state_changed() -> void: if physics_ball.sleeping and phase == Phase.SHOT: - phase = Phase.FINISHED + end_shot_track() + + +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") diff --git a/src/player/shot_setup/shot_setup.tscn b/src/player/shot_setup/shot_setup.tscn index 93d8d38..9c2cb18 100644 --- a/src/player/shot_setup/shot_setup.tscn +++ b/src/player/shot_setup/shot_setup.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=35 format=3 uid="uid://cy7t2tc4y3b4"] +[gd_scene load_steps=38 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"] @@ -203,6 +203,7 @@ _data = { } [sub_resource type="Animation" id="Animation_3xds6"] +resource_name = "RESET" length = 0.001 tracks/0/type = "value" tracks/0/imported = false @@ -274,10 +275,10 @@ tracks/0/path = NodePath(".:visible") tracks/0/interp = 1 tracks/0/loop_wrap = true tracks/0/keys = { -"times": PackedFloat32Array(0), -"transitions": PackedFloat32Array(1), +"times": PackedFloat32Array(0, 2.4), +"transitions": PackedFloat32Array(1, 1), "update": 1, -"values": [true] +"values": [true, false] } tracks/1/type = "value" tracks/1/imported = false @@ -332,6 +333,151 @@ _data = { "display": SubResource("Animation_cwotn") } +[sub_resource type="Animation" id="Animation_2gt87"] +resource_name = "RESET" +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:visible") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [false] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath(".:visible_ratio") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [1.0] +} +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath(".:rotation") +tracks/2/interp = 3 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 0, +"values": [7.31612e-10] +} +tracks/3/type = "bezier" +tracks/3/imported = false +tracks/3/enabled = true +tracks/3/path = NodePath(".:anchor_top") +tracks/3/interp = 1 +tracks/3/loop_wrap = true +tracks/3/keys = { +"handle_modes": PackedInt32Array(0), +"points": PackedFloat32Array(0.5, -0.25, 0, 0.25, 0), +"times": PackedFloat32Array(0) +} +tracks/4/type = "bezier" +tracks/4/imported = false +tracks/4/enabled = true +tracks/4/path = NodePath(".:anchor_bottom") +tracks/4/interp = 1 +tracks/4/loop_wrap = true +tracks/4/keys = { +"handle_modes": PackedInt32Array(0), +"points": PackedFloat32Array(0.5, -0.25, 0, 0.25, 0), +"times": PackedFloat32Array(0) +} + +[sub_resource type="Animation" id="Animation_g52q7"] +resource_name = "display" +length = 3.4 +step = 0.1 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath(".:visible") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0, 3.4), +"transitions": PackedFloat32Array(1, 1), +"update": 1, +"values": [true, false] +} +tracks/1/type = "value" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath(".:visible_ratio") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0, 0.4), +"transitions": PackedFloat32Array(1, 1), +"update": 0, +"values": [0.0, 1.0] +} +tracks/2/type = "value" +tracks/2/imported = false +tracks/2/enabled = true +tracks/2/path = NodePath(".:rotation") +tracks/2/interp = 3 +tracks/2/loop_wrap = true +tracks/2/keys = { +"times": PackedFloat32Array(0, 3, 3.4), +"transitions": PackedFloat32Array(1, 0.618, 1), +"update": 0, +"values": [7.31612e-10, 7.31612e-10, -2.96706] +} +tracks/3/type = "bezier" +tracks/3/imported = false +tracks/3/enabled = true +tracks/3/path = NodePath(".:anchor_top") +tracks/3/interp = 1 +tracks/3/loop_wrap = true +tracks/3/keys = { +"handle_modes": PackedInt32Array(0, 0, 0), +"points": PackedFloat32Array(0.5, -0.25, 0, 0.5, -0.0548477, 0.5, -0.4, 0.0593877, 0.233401, -0.456136, 1.25, -0.25, 0, 0.25, 0), +"times": PackedFloat32Array(0, 3, 3.4) +} +tracks/4/type = "bezier" +tracks/4/imported = false +tracks/4/enabled = true +tracks/4/path = NodePath(".:anchor_bottom") +tracks/4/interp = 1 +tracks/4/loop_wrap = true +tracks/4/keys = { +"handle_modes": PackedInt32Array(0, 0, 0), +"points": PackedFloat32Array(0.5, -0.25, 0, 0.5, -0.055, 0.5, -0.4, 0.059, 0.233, -0.456, 1.25, -0.25, 0, 0.25, 0), +"times": PackedFloat32Array(0, 3, 3.4) +} +tracks/5/type = "method" +tracks/5/imported = false +tracks/5/enabled = true +tracks/5/path = NodePath("../..") +tracks/5/interp = 1 +tracks/5/loop_wrap = true +tracks/5/keys = { +"times": PackedFloat32Array(3.4), +"transitions": PackedFloat32Array(1), +"values": [{ +"args": [], +"method": &"return_ball" +}] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_gbnnr"] +_data = { +"RESET": SubResource("Animation_2gt87"), +"display": SubResource("Animation_g52q7") +} + [sub_resource type="Animation" id="Animation_pk1s7"] length = 0.001 tracks/0/type = "bezier" @@ -634,6 +780,39 @@ libraries = { "": SubResource("AnimationLibrary_2a0gn") } +[node name="WastedFeedback" type="RichTextLabel" parent="ShotUI"] +visible = false +custom_minimum_size = Vector2(1400, 0) +layout_mode = 1 +anchors_preset = -1 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -350.0 +offset_top = -66.0 +offset_right = 350.0 +offset_bottom = 66.0 +grow_horizontal = 2 +grow_vertical = 2 +pivot_offset = Vector2(100, 115) +mouse_filter = 2 +theme_override_colors/font_shadow_color = Color(0, 0, 0, 1) +theme_override_constants/shadow_offset_y = 4 +theme_override_constants/shadow_offset_x = 6 +theme_override_font_sizes/bold_italics_font_size = 168 +bbcode_enabled = true +text = "[center][tornado radius=20][color=powder_blue][i][b]WASTED[/b][/i][/color][/tornado][/center]" +fit_content = true +autowrap_mode = 0 +visible_characters_behavior = 1 + +[node name="WastedAnimation" type="AnimationPlayer" parent="ShotUI/WastedFeedback"] +unique_name_in_owner = true +libraries = { +"": SubResource("AnimationLibrary_gbnnr") +} + [node name="ShotGauges" type="Control" parent="ShotUI"] layout_mode = 1 anchor_left = 0.4 @@ -735,4 +914,5 @@ root_node = NodePath("%HUDStateMachine/..") tree_root = SubResource("AnimationNodeStateMachine_osrbp") anim_player = NodePath("../HUDAnimation") +[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/world/ball_zone/ball_zone.gd b/src/world/ball_zone/ball_zone.gd new file mode 100644 index 0000000..e75df8e --- /dev/null +++ b/src/world/ball_zone/ball_zone.gd @@ -0,0 +1,29 @@ +class_name BallZone extends Area3D +## A spatial area that has an effect on balls inside it. + +@export var water_hazard := false + + +func _ready() -> void: + body_entered.connect(_on_body_entered) + body_exited.connect(_on_body_exited) + + +func on_ball_entered(ball: GameBall) -> void: + if water_hazard: + ball.entered_water.emit() + + +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) + + +func _on_body_exited(body: Node3D) -> void: + if body is GameBall: + on_ball_exited(body as GameBall)