From fcbc8c6f0a247e53a9b0466e2922eef69174bfc1 Mon Sep 17 00:00:00 2001 From: Rob Kelly Date: Sat, 14 Dec 2024 19:52:05 -0700 Subject: [PATCH] Ball abilities & powerball --- assets/sprites/particles/dot.png | 3 + assets/sprites/particles/dot.png.import | 34 ++++ assets/text/text.csv | 2 + project.godot | 5 + src/equipment/balls/physics_ball/game_ball.gd | 15 ++ .../balls/physics_ball/physics_ball.tscn | 4 + src/equipment/balls/power_ball/power_ball.gd | 21 +++ .../balls/power_ball/power_ball.tscn | 146 ++++++++++++++++++ src/player/debug_player.tres | 3 +- src/player/shot_setup/ball_point.gd | 1 + src/player/shot_setup/shot_setup.gd | 3 + src/player/shot_setup/shot_setup.tscn | 7 - .../shot_hud/ball_selector/ball_selector.gd | 5 + .../shot_hud/ball_selector/ball_selector.tscn | 8 + 14 files changed, 249 insertions(+), 8 deletions(-) create mode 100644 assets/sprites/particles/dot.png create mode 100644 assets/sprites/particles/dot.png.import create mode 100644 src/equipment/balls/power_ball/power_ball.gd create mode 100644 src/equipment/balls/power_ball/power_ball.tscn diff --git a/assets/sprites/particles/dot.png b/assets/sprites/particles/dot.png new file mode 100644 index 0000000..aec3658 --- /dev/null +++ b/assets/sprites/particles/dot.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9c1acbff49c9c2fc0acf0bc6d6af089aa7e3bd86c05b096990a9ea3c9c2a254f +size 4366 diff --git a/assets/sprites/particles/dot.png.import b/assets/sprites/particles/dot.png.import new file mode 100644 index 0000000..aa09832 --- /dev/null +++ b/assets/sprites/particles/dot.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://67r5iwexjlsc" +path="res://.godot/imported/dot.png-46eaa8fd8a0d7b1e6fa2fbfd53dfe4ba.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://assets/sprites/particles/dot.png" +dest_files=["res://.godot/imported/dot.png-46eaa8fd8a0d7b1e6fa2fbfd53dfe4ba.ctex"] + +[params] + +compress/mode=0 +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/assets/text/text.csv b/assets/text/text.csv index 4846f1d..4ce5cc3 100644 --- a/assets/text/text.csv +++ b/assets/text/text.csv @@ -84,6 +84,7 @@ ACTION_shot_zoom_out,"Zoom out" ACTION_shot_accept,Shoot ACTION_shot_cancel,"Cancel shot" ACTION_shot_reset,"Reset shot" +ACTION_activate_ball,"Activate ball ability" ACTION_select_driver,"Select driver" ACTION_select_iron,"Select iron" ACTION_select_wedge,"Select wedge" @@ -105,3 +106,4 @@ BALL_BASIC,Basic BALL_PLASMA,Plasma BALL_BRICK,Brick BALL_BEACH,"Beach Ball" +BALL_POWER,Powerball diff --git a/project.godot b/project.godot index c2e857a..c988148 100644 --- a/project.godot +++ b/project.godot @@ -143,6 +143,11 @@ shot_reset={ "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) ] } +activate_ball={ +"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":32,"key_label":0,"unicode":32,"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) diff --git a/src/equipment/balls/physics_ball/game_ball.gd b/src/equipment/balls/physics_ball/game_ball.gd index 65c5dd3..f7ed050 100644 --- a/src/equipment/balls/physics_ball/game_ball.gd +++ b/src/equipment/balls/physics_ball/game_ball.gd @@ -11,6 +11,7 @@ enum Type { PLASMA, BRICK, BEACH, + POWER, } const TERRAIN_DAMPING_EPSILON := 1e-6 @@ -52,6 +53,7 @@ var _position_on_last_wake: Vector3 var _awake := false var _zones: Array[BallZone] = [] +@onready var ability_cooldown: Timer = %AbilityCooldown @onready var manual_sleep_timer: Timer = %ManualSleepTimer @onready var sfx: BallSFX = %SFX @onready var effects: BallParticleEffects = %ParticleEffects @@ -71,6 +73,19 @@ func enter_water() -> void: entered_water.emit() +## Activate this ball's ability, if there is one. +func activate_ability() -> void: + if ability_cooldown.is_stopped(): + _activate_ability() + ability_cooldown.start() + # TODO: bonk + + +func _activate_ability() -> void: + # Implmemented by derived type + pass + + func get_damage() -> float: print("velocity: ", linear_velocity.length()) return base_damage + linear_velocity.length_squared() * damage_force_scale diff --git a/src/equipment/balls/physics_ball/physics_ball.tscn b/src/equipment/balls/physics_ball/physics_ball.tscn index 71c0011..d217347 100644 --- a/src/equipment/balls/physics_ball/physics_ball.tscn +++ b/src/equipment/balls/physics_ball/physics_ball.tscn @@ -193,6 +193,10 @@ bus = &"SFX" unique_name_in_owner = true one_shot = true +[node name="AbilityCooldown" type="Timer" parent="."] +unique_name_in_owner = true +one_shot = true + [node name="ParticleEffects" type="Node3D" parent="."] unique_name_in_owner = true script = ExtResource("12_7krl6") diff --git a/src/equipment/balls/power_ball/power_ball.gd b/src/equipment/balls/power_ball/power_ball.gd new file mode 100644 index 0000000..5656c93 --- /dev/null +++ b/src/equipment/balls/power_ball/power_ball.gd @@ -0,0 +1,21 @@ +extends GameBall + +const ABILITY_MAGNITUDE := 5.0 + +var _ability_impulse := Vector3.ZERO + +@onready var powerball_animation: AnimationPlayer = %PowerballAnimation + + +func _activate_ability() -> void: + _ability_impulse = linear_velocity.normalized() * ABILITY_MAGNITUDE + can_sleep = false + freeze = true + powerball_animation.play("activate") + + +func _finish_ability() -> void: + can_sleep = true + freeze = false + linear_velocity = Vector3.ZERO + apply_central_impulse(_ability_impulse) diff --git a/src/equipment/balls/power_ball/power_ball.tscn b/src/equipment/balls/power_ball/power_ball.tscn new file mode 100644 index 0000000..92ec6a5 --- /dev/null +++ b/src/equipment/balls/power_ball/power_ball.tscn @@ -0,0 +1,146 @@ +[gd_scene load_steps=18 format=3 uid="uid://deuytmxw2lc62"] + +[ext_resource type="PackedScene" uid="uid://dfttci386ohip" path="res://src/equipment/balls/physics_ball/physics_ball.tscn" id="1_14gld"] +[ext_resource type="Texture2D" uid="uid://ckhiq6rfjv63u" path="res://assets/textures/gfolfball/gfolfball.png" id="2_a2gtg"] +[ext_resource type="Script" path="res://src/equipment/balls/power_ball/power_ball.gd" id="2_hy51e"] +[ext_resource type="Texture2D" uid="uid://btntjs7mbdigu" path="res://assets/textures/gfolfball/gfolfball_normal.png" id="3_60i75"] + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_c4cm7"] +albedo_color = Color(2, 0.266, 0.266, 1) +albedo_texture = ExtResource("2_a2gtg") +albedo_texture_force_srgb = true +metallic = 1.0 +roughness = 0.67 +normal_enabled = true +normal_scale = 0.2 +normal_texture = ExtResource("3_60i75") +clearcoat_roughness = 0.0 +uv1_scale = Vector3(3, 1.5, 3) +texture_filter = 4 + +[sub_resource type="SphereMesh" id="SphereMesh_0b0i7"] +material = SubResource("StandardMaterial3D_c4cm7") +radius = 0.05 +height = 0.1 +radial_segments = 6 +rings = 6 + +[sub_resource type="Curve" id="Curve_ai354"] +max_value = 100.0 +_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(0.115, 100), 0.0, 0.0, 0, 0] +point_count = 2 + +[sub_resource type="CurveTexture" id="CurveTexture_g3kms"] +curve = SubResource("Curve_ai354") + +[sub_resource type="Curve" id="Curve_jeoyl"] +_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(0.709474, 0), 0.0, 0.0, 0, 0] +point_count = 2 + +[sub_resource type="CurveTexture" id="CurveTexture_c2myg"] +curve = SubResource("Curve_jeoyl") + +[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_k07ua"] +emission_shape = 2 +emission_sphere_radius = 2.0 +gravity = Vector3(0, 0, 0) +radial_accel_min = -100.0 +radial_accel_max = -100.0 +damping_min = 1.0 +damping_max = 1.0 +damping_curve = SubResource("CurveTexture_g3kms") +scale_curve = SubResource("CurveTexture_c2myg") + +[sub_resource type="Curve" id="Curve_p1ob2"] +_data = [Vector2(0, 0), 0.0, 13.0505, 0, 0, Vector2(0.185404, 1), 0.0, 0.0, 0, 0, Vector2(0.986193, 0), 0.0, 0.0, 0, 0] +point_count = 3 + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_v3vpa"] +cull_mode = 2 +shading_mode = 0 +vertex_color_use_as_albedo = true +albedo_color = Color(2, 2, 1.333, 1) +use_particle_trails = true + +[sub_resource type="RibbonTrailMesh" id="RibbonTrailMesh_elifs"] +material = SubResource("StandardMaterial3D_v3vpa") +shape = 0 +size = 0.1 +sections = 3 +section_length = 0.1 +curve = SubResource("Curve_p1ob2") + +[sub_resource type="Animation" id="Animation_7yrvu"] +resource_name = "activate" +length = 0.8 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("ParticleEffects/PowerParticles:emitting") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [true] +} +tracks/1/type = "method" +tracks/1/imported = false +tracks/1/enabled = true +tracks/1/path = NodePath(".") +tracks/1/interp = 1 +tracks/1/loop_wrap = true +tracks/1/keys = { +"times": PackedFloat32Array(0.8), +"transitions": PackedFloat32Array(1), +"values": [{ +"args": [], +"method": &"_finish_ability" +}] +} + +[sub_resource type="Animation" id="Animation_6c6mi"] +length = 0.001 +tracks/0/type = "value" +tracks/0/imported = false +tracks/0/enabled = true +tracks/0/path = NodePath("ParticleEffects/PowerParticles:emitting") +tracks/0/interp = 1 +tracks/0/loop_wrap = true +tracks/0/keys = { +"times": PackedFloat32Array(0), +"transitions": PackedFloat32Array(1), +"update": 1, +"values": [false] +} + +[sub_resource type="AnimationLibrary" id="AnimationLibrary_ospg0"] +_data = { +"RESET": SubResource("Animation_6c6mi"), +"activate": SubResource("Animation_7yrvu") +} + +[node name="PowerBall" instance=ExtResource("1_14gld")] +freeze_mode = 1 +script = ExtResource("2_hy51e") + +[node name="BallMesh" parent="." index="0"] +mesh = SubResource("SphereMesh_0b0i7") + +[node name="PowerParticles" type="GPUParticles3D" parent="ParticleEffects" index="1"] +emitting = false +amount = 32 +lifetime = 0.8 +one_shot = true +randomness = 1.0 +trail_enabled = true +trail_lifetime = 0.4 +process_material = SubResource("ParticleProcessMaterial_k07ua") +draw_pass_1 = SubResource("RibbonTrailMesh_elifs") + +[node name="PowerballAnimation" type="AnimationPlayer" parent="." index="7"] +unique_name_in_owner = true +libraries = { +"": SubResource("AnimationLibrary_ospg0") +} diff --git a/src/player/debug_player.tres b/src/player/debug_player.tres index 3c17dc1..714245e 100644 --- a/src/player/debug_player.tres +++ b/src/player/debug_player.tres @@ -19,5 +19,6 @@ _balls = { 1: -1, 2: 5, 3: -1, -4: -1 +4: -1, +5: -1 } diff --git a/src/player/shot_setup/ball_point.gd b/src/player/shot_setup/ball_point.gd index ecc88c3..c657d2f 100644 --- a/src/player/shot_setup/ball_point.gd +++ b/src/player/shot_setup/ball_point.gd @@ -10,6 +10,7 @@ const SCENE_MAP: Dictionary = { GameBall.Type.PLASMA: preload("res://src/equipment/balls/plasma_ball/plasma_ball.tscn"), GameBall.Type.BRICK: preload("res://src/equipment/balls/brick/brick.tscn"), GameBall.Type.BEACH: preload("res://src/equipment/balls/beach_ball/beach_ball.tscn"), + GameBall.Type.POWER: preload("res://src/equipment/balls/power_ball/power_ball.tscn"), } @export var ball: GameBall: diff --git a/src/player/shot_setup/shot_setup.gd b/src/player/shot_setup/shot_setup.gd index 90549ad..1672b50 100644 --- a/src/player/shot_setup/shot_setup.gd +++ b/src/player/shot_setup/shot_setup.gd @@ -619,6 +619,9 @@ func _process(delta: float) -> void: reset_enabled = false return_ball() + if Input.is_action_just_pressed("activate_ball"): + game_ball.activate_ability() + if driving_range and Input.is_action_just_pressed("shot_accept"): phase = Phase.AIM return_ball() diff --git a/src/player/shot_setup/shot_setup.tscn b/src/player/shot_setup/shot_setup.tscn index 451068b..7ecba9b 100644 --- a/src/player/shot_setup/shot_setup.tscn +++ b/src/player/shot_setup/shot_setup.tscn @@ -426,13 +426,6 @@ stream_0/stream = ExtResource("15_fn6g1") [node name="ShotSetup" type="Node3D"] script = ExtResource("1_r6ei4") -driving_range = null -initial_club_type = null -initial_ball = null -base_power = null -base_curve = null -perfect_aim = null -keep_projection = null [node name="BallPoint" type="Node3D" parent="."] unique_name_in_owner = true diff --git a/src/ui/shot_hud/ball_selector/ball_selector.gd b/src/ui/shot_hud/ball_selector/ball_selector.gd index 70acbb3..62f09c3 100644 --- a/src/ui/shot_hud/ball_selector/ball_selector.gd +++ b/src/ui/shot_hud/ball_selector/ball_selector.gd @@ -9,6 +9,7 @@ const Y_OFFSET := { GameBall.Type.PLASMA: -14, GameBall.Type.BRICK: -46, GameBall.Type.BEACH: -78, + GameBall.Type.POWER: -110, } @export var value: GameBall.Type: @@ -19,6 +20,7 @@ const Y_OFFSET := { @onready var plasma_icon: BallIcon = %PlasmaIcon @onready var brick_icon: BallIcon = %BrickIcon @onready var beach_icon: BallIcon = %BeachIcon +@onready var power_icon: BallIcon = %PowerIcon func _ready() -> void: @@ -31,6 +33,7 @@ func set_state_for_player(player: WorldPlayer) -> void: plasma_icon.quantity = player.get_balls(GameBall.Type.PLASMA) brick_icon.quantity = player.get_balls(GameBall.Type.BRICK) beach_icon.quantity = player.get_balls(GameBall.Type.BEACH) + power_icon.quantity = player.get_balls(GameBall.Type.POWER) if player.shot_setup: value = player.shot_setup.ball_type player.on_balls_changed.connect(_set_quantity) @@ -46,6 +49,8 @@ func _get_icon(type: GameBall.Type) -> BallIcon: return brick_icon GameBall.Type.BEACH: return beach_icon + GameBall.Type.POWER: + return power_icon return null diff --git a/src/ui/shot_hud/ball_selector/ball_selector.tscn b/src/ui/shot_hud/ball_selector/ball_selector.tscn index 41aa36d..6bb46f2 100644 --- a/src/ui/shot_hud/ball_selector/ball_selector.tscn +++ b/src/ui/shot_hud/ball_selector/ball_selector.tscn @@ -76,3 +76,11 @@ layout_mode = 2 text = "BALL_BEACH" quantity = 0 empty = true + +[node name="PowerIcon" parent="GradientMask/BallList" instance=ExtResource("1_1v8xg")] +unique_name_in_owner = true +custom_minimum_size = Vector2(120, 27) +layout_mode = 2 +text = "BALL_POWER" +quantity = 0 +empty = true