Ball can be reset after traveling for 45 seconds

This commit is contained in:
Rob Kelly 2024-12-07 17:57:58 -07:00
parent d8dbf0a7d1
commit 317f77c358
6 changed files with 202 additions and 4 deletions

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=60 format=3 uid="uid://bm2o3mex10v11"]
[gd_scene load_steps=61 format=3 uid="uid://bm2o3mex10v11"]
[ext_resource type="Terrain3DAssets" uid="uid://cwl34gstabgrx" path="res://levels/debug_level/terrain_assets.res" id="1_5smdk"]
[ext_resource type="Shader" path="res://src/shaders/psx_water.gdshader" id="6_0efu4"]
@ -286,6 +286,10 @@ albedo_texture = ExtResource("18_scall")
uv1_scale = Vector3(4, 2, 1)
texture_filter = 4
[sub_resource type="CylinderShape3D" id="CylinderShape3D_f1rqf"]
height = 32.0
radius = 32.0
[sub_resource type="CylinderShape3D" id="CylinderShape3D_sqfj0"]
height = 55.0
radius = 100.0
@ -604,7 +608,7 @@ gravity = -9.8
[node name="CollisionShape3D" type="CollisionShape3D" parent="GravityBowl/Area3D"]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 16, 0)
shape = SubResource("CylinderShape3D_sqfj0")
shape = SubResource("CylinderShape3D_f1rqf")
[node name="GravityHalo" type="Node3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 73.1897, 78.0923, 345.794)

View File

@ -132,6 +132,11 @@ shot_cancel={
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":81,"key_label":0,"unicode":113,"location":0,"echo":false,"script":null)
]
}
shot_reset={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":82,"key_label":0,"unicode":114,"location":0,"echo":false,"script":null)
]
}
select_driver={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":49,"key_label":0,"unicode":49,"location":0,"echo":false,"script":null)

View File

@ -8,6 +8,7 @@ enum Phase {
CURVE_ADJUST,
DOWNSWING,
SHOT,
SHOT_RESET,
FINISHED,
}
@ -87,6 +88,15 @@ var invert_pitch: bool = ProjectSettings.get_setting("game/config/controls/camer
var control_disabled := false
var reset_enabled := false:
set(value):
if value != reset_enabled:
if value:
hud.show_reset_prompt()
else:
hud.hide_reset_prompt()
reset_enabled = value
var phase: Phase = Phase.FINISHED:
set(value):
if value != phase:
@ -158,6 +168,7 @@ var _tracking_camera: OrbitalCamera
@onready var downswing_timer: Timer = %DownswingTimer
@onready var ball_return_timer: Timer = %BallReturnTimer
@onready var reset_prompt_timer: Timer = %ResetPromptTimer
@onready var explosion_animation: AnimationPlayer = %ExplosionAnimation
@onready var player_label: Label3D = %PlayerLabel
@ -273,6 +284,8 @@ func take_shot() -> void:
game_ball.freeze = false
game_ball.apply_impulse(impulse, offset)
reset_prompt_timer.start()
# Play SFX
shot_sfx.play_shot_sfx(club_type, is_shot_good(), shot_power)
@ -375,7 +388,7 @@ func end_shot_track() -> void:
camera.make_current()
if is_instance_valid(_tracking_camera):
_tracking_camera.queue_free()
if phase == Phase.SHOT:
if phase in [Phase.SHOT, Phase.SHOT_RESET]:
phase = Phase.FINISHED
@ -418,6 +431,9 @@ func _set_club_type(new_club_type: Club.Type) -> void:
## Called immediately before `phase` is mutated.
func _on_phase_change(new_phase: Phase) -> void:
reset_prompt_timer.stop()
reset_enabled = false
match new_phase:
Phase.AIM:
hud.show_hud()
@ -569,6 +585,11 @@ func _process(delta: float) -> void:
hud.stop_curve_bar()
phase = Phase.DOWNSWING
Phase.SHOT:
if reset_enabled and Input.is_action_just_pressed("shot_reset"):
phase = Phase.SHOT_RESET
reset_enabled = false
return_ball()
if driving_range and Input.is_action_just_pressed("shot_accept"):
phase = Phase.AIM
return_ball()
@ -587,6 +608,7 @@ func _on_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:
phase = Phase.SHOT_RESET
game_ball.freeze = true
hud.play_wasted_animation()
player.life -= WATER_DAMAGE
@ -617,6 +639,10 @@ func _on_hitbox_ball_collision(ball: GameBall) -> void:
ball.apply_central_impulse(explosion_impulse)
func _on_reset_prompt_timer_timeout() -> void:
reset_enabled = true
## Create a new instance for the given player.
static func create(_player: WorldPlayer) -> ShotSetup:
var instance: ShotSetup = ShotSetup.scene.instantiate()

View File

@ -451,6 +451,11 @@ one_shot = true
unique_name_in_owner = true
one_shot = true
[node name="ResetPromptTimer" type="Timer" parent="."]
unique_name_in_owner = true
wait_time = 45.0
one_shot = true
[node name="Hitbox" type="Area3D" parent="."]
script = ExtResource("7_uh8kn")
@ -498,5 +503,6 @@ width = 120.0
[connection signal="ball_changed" from="BallPoint" to="." method="_on_game_ball_changed"]
[connection signal="timeout" from="DownswingTimer" to="." method="finish_downswing"]
[connection signal="timeout" from="BallReturnTimer" to="." method="_on_ball_return_timer_timeout"]
[connection signal="timeout" from="ResetPromptTimer" to="." method="_on_reset_prompt_timer_timeout"]
[connection signal="ball_collision" from="Hitbox" to="." method="_on_hitbox_ball_collision"]
[connection signal="body_entered" from="Hitbox" to="Hitbox" method="_on_body_entered"]

View File

@ -26,6 +26,8 @@ var player: WorldPlayer
@onready var _player_name: Label = %PlayerName
@onready var _reset_prompt_animation: AnimationPlayer = %ResetPromptAnimation
@onready var _life_bar_rumbler: Rumbler = %LifeBarRumbler
static var scene: PackedScene = preload("res://src/ui/shot_hud/shot_hud.tscn")
@ -93,6 +95,13 @@ func play_wasted_animation() -> void:
_wasted_animation.play("display")
func show_reset_prompt() -> void:
_reset_prompt_animation.play("show")
func hide_reset_prompt() -> void:
_reset_prompt_animation.play_backwards("show")
## Set the value of the life bar, potentially playing some kind of effect in response.
##
## To set the life bar without triggering an effect, set it directly with `life_bar.value`

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=38 format=3 uid="uid://c4ifdiohng830"]
[gd_scene load_steps=47 format=3 uid="uid://c4ifdiohng830"]
[ext_resource type="Script" path="res://src/ui/shot_hud/shot_hud.gd" id="1_x5b4c"]
[ext_resource type="Shader" path="res://src/shaders/canvas_retro.gdshader" id="1_ybxxp"]
@ -13,6 +13,7 @@
[ext_resource type="FontFile" uid="uid://dsa0oh7c0h4pu" path="res://assets/fonts/Racing_Sans_One/RacingSansOne-Regular.ttf" id="8_bejx4"]
[ext_resource type="Texture2D" uid="uid://tancoet1lih5" path="res://assets/ui/ball_icons/basic_icon.png" id="8_tt8i3"]
[ext_resource type="PackedScene" uid="uid://dmciuk3pbjsae" path="res://src/ui/shot_hud/life_bar/life_bar.tscn" id="9_w1fiw"]
[ext_resource type="PackedScene" uid="uid://b47goj32i6sdh" path="res://src/ui/input_prompt/input_prompt.tscn" id="14_ik4gg"]
[sub_resource type="Animation" id="Animation_3xds6"]
resource_name = "RESET"
@ -642,6 +643,114 @@ _data = {
"show": SubResource("Animation_nicro")
}
[sub_resource type="Gradient" id="Gradient_jevda"]
interpolation_mode = 2
offsets = PackedFloat32Array(0, 0.5, 1)
colors = PackedColorArray(0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0)
[sub_resource type="GradientTexture2D" id="GradientTexture2D_q43a6"]
gradient = SubResource("Gradient_jevda")
fill_from = Vector2(0, 0.4)
fill_to = Vector2(1, 0.6)
metadata/_snap_enabled = true
[sub_resource type="Animation" id="Animation_ornnh"]
resource_name = "idle"
length = 6.0
loop_mode = 1
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Glint:anchor_left")
tracks/0/interp = 2
tracks/0/loop_wrap = false
tracks/0/keys = {
"times": PackedFloat32Array(0, 0.233333),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [-1.0, 1.0]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Glint:anchor_right")
tracks/1/interp = 2
tracks/1/loop_wrap = false
tracks/1/keys = {
"times": PackedFloat32Array(0, 0.233333),
"transitions": PackedFloat32Array(1, 1),
"update": 0,
"values": [0.0, 2.0]
}
[sub_resource type="Animation" id="Animation_3dab1"]
length = 0.001
tracks/0/type = "value"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath("Glint:anchor_left")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [-1.0]
}
tracks/1/type = "value"
tracks/1/imported = false
tracks/1/enabled = true
tracks/1/path = NodePath("Glint:anchor_right")
tracks/1/interp = 1
tracks/1/loop_wrap = true
tracks/1/keys = {
"times": PackedFloat32Array(0),
"transitions": PackedFloat32Array(1),
"update": 0,
"values": [0.0]
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_bdkm3"]
_data = {
"RESET": SubResource("Animation_3dab1"),
"idle": SubResource("Animation_ornnh")
}
[sub_resource type="Animation" id="Animation_ll1u8"]
resource_name = "show"
length = 0.4
tracks/0/type = "bezier"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:position:y")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"handle_modes": PackedInt32Array(0, 0),
"points": PackedFloat32Array(-55, -0.25, 0, 0.0709939, 50.4391, 0, -0.251647, 15.8692, 0.2, 0),
"times": PackedFloat32Array(0, 0.4)
}
[sub_resource type="Animation" id="Animation_qjs4v"]
length = 0.001
tracks/0/type = "bezier"
tracks/0/imported = false
tracks/0/enabled = true
tracks/0/path = NodePath(".:position:y")
tracks/0/interp = 1
tracks/0/loop_wrap = true
tracks/0/keys = {
"handle_modes": PackedInt32Array(0),
"points": PackedFloat32Array(-55, -0.25, 0, 0.25, 0),
"times": PackedFloat32Array(0)
}
[sub_resource type="AnimationLibrary" id="AnimationLibrary_o70c6"]
_data = {
"RESET": SubResource("Animation_qjs4v"),
"show": SubResource("Animation_ll1u8")
}
[node name="ShotHUD" type="Control"]
layout_mode = 3
anchors_preset = 15
@ -920,3 +1029,42 @@ root_node = NodePath("../..")
libraries = {
"": SubResource("AnimationLibrary_c3i4w")
}
[node name="ResetPrompt" type="MarginContainer" parent="."]
layout_mode = 1
anchors_preset = -1
anchor_left = 0.5
anchor_right = 0.5
offset_left = -95.5
offset_top = -55.0
offset_right = 95.5
grow_horizontal = 2
theme_override_constants/margin_top = 16
[node name="ResetInputPrompt" parent="ResetPrompt" instance=ExtResource("14_ik4gg")]
clip_children = 2
layout_mode = 2
text = "❓ - RESET"
action = &"shot_reset"
label = "RESET"
[node name="Glint" type="TextureRect" parent="ResetPrompt/ResetInputPrompt"]
layout_mode = 1
anchors_preset = -1
anchor_left = -1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
texture = SubResource("GradientTexture2D_q43a6")
[node name="GlintAnimation" type="AnimationPlayer" parent="ResetPrompt/ResetInputPrompt"]
libraries = {
"": SubResource("AnimationLibrary_bdkm3")
}
autoplay = "idle"
[node name="ResetPromptAnimation" type="AnimationPlayer" parent="ResetPrompt"]
unique_name_in_owner = true
libraries = {
"": SubResource("AnimationLibrary_o70c6")
}