diff --git a/levels/debug_level/terrain_3d_data/terrain3d_00_00.res b/levels/debug_level/terrain_3d_data/terrain3d_00_00.res index 78db045..2e27de7 100644 --- a/levels/debug_level/terrain_3d_data/terrain3d_00_00.res +++ b/levels/debug_level/terrain_3d_data/terrain3d_00_00.res @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:3633fe2ef5b54d9311e490436429376909b308ecb2769ec8563071822c26c9b4 -size 547143 +oid sha256:514eadfc09a4f96e7e1324bde794df1b6ee03204d19fe6a9825d48183808a8f8 +size 554768 diff --git a/src/equipment/balls/physics_ball/ball_particle_effects.gd b/src/equipment/balls/physics_ball/ball_particle_effects.gd new file mode 100644 index 0000000..8d88a51 --- /dev/null +++ b/src/equipment/balls/physics_ball/ball_particle_effects.gd @@ -0,0 +1,16 @@ +class_name BallParticleEffects extends Node3D +## Controller for ball particle effects. + +@onready var sand_particles: GPUParticles3D = %SandParticles + +@onready var ball: GameBall = $".." + + +func play_effect(terrain: Terrain.Type) -> void: + global_rotation = Vector3.ZERO + match terrain: + Terrain.Type.SAND: + # Adjust sand particle direction + var material: ParticleProcessMaterial = sand_particles.process_material + material.direction = -ball.linear_velocity.normalized() + sand_particles.emitting = true diff --git a/src/equipment/balls/physics_ball/game_ball.gd b/src/equipment/balls/physics_ball/game_ball.gd index 0f8c351..63f15dd 100644 --- a/src/equipment/balls/physics_ball/game_ball.gd +++ b/src/equipment/balls/physics_ball/game_ball.gd @@ -45,6 +45,7 @@ var _zones: Array[BallZone] = [] @onready var manual_sleep_timer: Timer = %ManualSleepTimer @onready var sfx: BallSFX = %SFX +@onready var effects: BallParticleEffects = %ParticleEffects @onready var normal_physics: PhysicsMaterial = preload( "res://src/equipment/balls/physics_ball/normal_physics.tres" @@ -144,15 +145,20 @@ func _on_collision(body: Node) -> void: freeze = true manual_sleep_timer.start() + var terrain: Terrain.Type if body is Terrain3D: - sfx.play_sfx(Terrain.at_position(global_position, body as Terrain3D)) + terrain = Terrain.at_position(global_position, body as Terrain3D) elif body is CSGShape3D: - sfx.play_sfx(Terrain.from_physical_layer((body as CSGShape3D).collision_layer)) + terrain = Terrain.from_physical_layer((body as CSGShape3D).collision_layer) elif body is CollisionObject3D: - sfx.play_sfx(Terrain.from_physical_layer((body as CollisionObject3D).collision_layer)) + terrain = Terrain.from_physical_layer((body as CollisionObject3D).collision_layer) else: print_debug("COLLIDER: ", body) + if terrain: + sfx.play_sfx(terrain) + effects.play_effect(terrain) + func _fire_sleep_signal() -> void: sleeping = true diff --git a/src/equipment/balls/physics_ball/physics_ball.tscn b/src/equipment/balls/physics_ball/physics_ball.tscn index ea711ee..0899c67 100644 --- a/src/equipment/balls/physics_ball/physics_ball.tscn +++ b/src/equipment/balls/physics_ball/physics_ball.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=19 format=3 uid="uid://dfttci386ohip"] +[gd_scene load_steps=24 format=3 uid="uid://dfttci386ohip"] [ext_resource type="Script" path="res://src/equipment/balls/physics_ball/game_ball.gd" id="1_iwh2u"] [ext_resource type="PhysicsMaterial" uid="uid://3bih72l068ic" path="res://src/equipment/balls/physics_ball/normal_physics.tres" id="1_l23pw"] @@ -11,6 +11,8 @@ [ext_resource type="AudioStream" uid="uid://3csnnhxndt67" path="res://assets/sound/sfx/ball/concrete5.wav" id="9_p0lmw"] [ext_resource type="AudioStream" uid="uid://bbbp6wrkuhkek" path="res://assets/sound/sfx/ball/sand1.wav" id="10_b64mx"] [ext_resource type="AudioStream" uid="uid://b5xx5t050i4p" path="res://assets/sound/sfx/ball/sand2.wav" id="11_ed8je"] +[ext_resource type="Script" path="res://src/equipment/balls/physics_ball/ball_particle_effects.gd" id="12_7krl6"] +[ext_resource type="Texture2D" uid="uid://c47bkx508biqr" path="res://assets/sprites/particles/plasma.png" id="12_guipt"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_xqofq"] albedo_texture = ExtResource("1_y3q5j") @@ -92,6 +94,33 @@ streams_count = 2 stream_0/stream = ExtResource("10_b64mx") stream_1/stream = ExtResource("11_ed8je") +[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_mwiw1"] +angle_min = -720.0 +angle_max = 720.0 +spread = 20.0 +initial_velocity_min = 1.0 +initial_velocity_max = 3.0 +gravity = Vector3(0, -3, 0) +scale_min = 0.0 +hue_variation_min = -0.02 +hue_variation_max = -2.23517e-08 + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_v1i8b"] +transparency = 1 +vertex_color_use_as_albedo = true +albedo_color = Color(0.78, 0.70928, 0.5304, 1) +albedo_texture = ExtResource("12_guipt") +texture_filter = 4 +billboard_mode = 3 +billboard_keep_scale = true +particles_anim_h_frames = 1 +particles_anim_v_frames = 1 +particles_anim_loop = false + +[sub_resource type="QuadMesh" id="QuadMesh_xkteo"] +material = SubResource("StandardMaterial3D_v1i8b") +size = Vector2(0.2, 0.2) + [node name="PhysicsBall" type="RigidBody3D"] mass = 0.05 physics_material_override = ExtResource("1_l23pw") @@ -149,6 +178,19 @@ bus = &"SFX" unique_name_in_owner = true one_shot = true +[node name="ParticleEffects" type="Node3D" parent="."] +unique_name_in_owner = true +script = ExtResource("12_7krl6") + +[node name="SandParticles" type="GPUParticles3D" parent="ParticleEffects"] +unique_name_in_owner = true +emitting = false +amount = 24 +one_shot = true +explosiveness = 0.9 +process_material = SubResource("ParticleProcessMaterial_mwiw1") +draw_pass_1 = SubResource("QuadMesh_xkteo") + [connection signal="body_entered" from="." to="." method="_on_collision"] [connection signal="sleeping_state_changed" from="." to="." method="_on_sleeping_state_changed"] [connection signal="timeout" from="ManualSleepTimer" to="." method="_fire_sleep_signal"] diff --git a/src/player/shot_setup/shot_setup.gd b/src/player/shot_setup/shot_setup.gd index f0543b2..007451a 100644 --- a/src/player/shot_setup/shot_setup.gd +++ b/src/player/shot_setup/shot_setup.gd @@ -96,10 +96,7 @@ var phase: Phase = Phase.FINISHED: var hud: ShotHUD var club_type: Club.Type: - set(value): - if value != club_type: - _on_club_change(value) - club_type = value + set = _set_club_type var club: Club: get: @@ -382,8 +379,10 @@ func end_shot_track() -> void: phase = Phase.FINISHED -## Called immediately before `club` is mutated. -func _on_club_change(new_club_type: Club.Type) -> void: +func _set_club_type(new_club_type: Club.Type) -> void: + if new_club_type == club_type: + return + var new_club := player.get_club(new_club_type) if not new_club: # `new_club` will be null if player has no club in the given slot @@ -414,6 +413,8 @@ func _on_club_change(new_club_type: Club.Type) -> void: _: print_debug("Not sure how to equip club type: ", new_club) + club_type = new_club_type + ## Called immediately before `phase` is mutated. func _on_phase_change(new_phase: Phase) -> void: