diff --git a/levels/debug_level/debug_level.tscn b/levels/debug_level/debug_level.tscn index fd855bc..24e9bc5 100644 --- a/levels/debug_level/debug_level.tscn +++ b/levels/debug_level/debug_level.tscn @@ -41,6 +41,7 @@ _shader_parameters = { "vertex_normals_distance": 128.0 } texture_filtering = 1 +show_navigation = true [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_ly4sm"] cull_mode = 2 @@ -199,3 +200,12 @@ mesh = SubResource("BoxMesh_20p1k") [node name="CollisionShape3D" type="CollisionShape3D" parent="DebugTable/StaticBody3D"] shape = SubResource("BoxShape3D_g31tw") + +[node name="Fairway" type="Area3D" parent="."] +script = ExtResource("9_jwlau") +terrain_angular_damping = 2.0 + +[node name="CollisionPolygon3D" type="CollisionPolygon3D" parent="Fairway"] +transform = Transform3D(1, 0, 0, 0, -4.37114e-08, -1, 0, 1, -4.37114e-08, 209.788, 6.20358, 256.527) +depth = 10.0 +polygon = PackedVector2Array(-1.47594, 8.77969, -12.788, 19.9447, -17.7778, 31.2864, -19.2001, 41.1398, -19.2001, 55.4081, -16.3465, 66.9813, -15.7123, 75.8594, -14.9196, 82.6765, -12.383, 89.9692, -5.6736, 102.186, 2.88742, 115.027, 9.22891, 125.332, 14.7777, 133.893, 23.4973, 146.417, 35.7046, 159.893, 44.1071, 167.661, 55.8437, 178.18, 64.5632, 185.314, 69.7949, 189.753, 73.7584, 193.082, 80.734, 200.85, 94.5267, 212.899, 106.576, 221.46, 127.915, 233.827, 139.647, 240.802, 170.403, 256.181, 183.721, 262.839, 204.489, 271.717, 216.062, 274.571, 224.465, 279.485, 235.727, 283.429, 246.983, 289.929, 253.958, 290.88, 265.373, 296.27, 275.044, 298.965, 288.995, 299.282, 302.154, 299.599, 330.056, 297.063, 356.532, 289.612, 370.483, 282.636, 382.057, 270.112, 388.081, 259.648, 392.679, 245.221, 395.849, 226.989, 395.863, 185.922, 391.266, 164.52, 381.913, 148.636, 362.889, 133.417, 344.657, 121.051, 327.059, 111.063, 306.291, 103.136, 292.974, 102.66, 277.913, 102.66, 264.913, 105.99, 241.347, 117.315, 222.323, 125.558, 203.457, 127.144, 182.371, 123.973, 157.322, 119.534, 132.908, 107.644, 108.651, 86.0827, 88.8301, 59.386, 82.6471, 48.764, 75.6715, 25.7761, 65.063, 10.562, 56.819, 3.7449, 48.5751, -0.852661, 35.2579, -3.07219, 20.8311, -3.38925, 7.35541, 1.36685) diff --git a/project.godot b/project.godot index 18dd3e6..d011191 100644 --- a/project.godot +++ b/project.godot @@ -151,7 +151,10 @@ select_putter={ [physics] 3d/physics_engine="JoltPhysics3D" -3d/sleep_threshold_angular=0.3 +3d/sleep_threshold_linear=0.1 +3d/sleep_threshold_angular=2.0 +jolt_3d/sleep/velocity_threshold=0.1 +jolt_3d/sleep/time_threshold=1.0 jolt_3d/limits/max_temporary_memory=64 [rendering] diff --git a/src/player/physics_ball/game_ball.gd b/src/player/physics_ball/game_ball.gd index e5e6f52..05a5c41 100644 --- a/src/player/physics_ball/game_ball.gd +++ b/src/player/physics_ball/game_ball.gd @@ -3,14 +3,61 @@ class_name GameBall extends RigidBody3D signal entered_water +const TERRAIN_DAMPING_EPSILON := 1e-6 +const IRON_DAMPING := 9999.0 + ## Angular damping while in air @export var air_damping := 0.0 ## Angular damping while in collision with rough terrain @export var rough_damping := 8.0 +## Angular damping for iron balls +@export var iron_damping := 9999.0 + +## Causes the ball to act more like a brick +@export var iron_ball := false: + set(value): + if value: + physics_material_override = iron_physics + else: + physics_material_override = normal_physics + iron_ball = value + +var _zones: Array[BallZone] = [] + +@onready +var normal_physics: PhysicsMaterial = preload("res://src/player/physics_ball/normal_physics.tres") +@onready +var iron_physics: PhysicsMaterial = preload("res://src/player/physics_ball/iron_physics.tres") + + +## Called by a water area when this ball enters it +func enter_water() -> void: + entered_water.emit() + + +func _total_terrain_angular_damping() -> float: + return _zones.reduce( + func(a: float, b: BallZone) -> float: return a + b.terrain_angular_damping, 0.0 + ) func _integrate_forces(state: PhysicsDirectBodyState3D) -> void: - if state.get_contact_count(): - angular_damp = rough_damping - else: - angular_damp = air_damping + var damping := air_damping + if iron_ball: + damping = iron_damping + elif state.get_contact_count(): + damping = _total_terrain_angular_damping() + if damping <= TERRAIN_DAMPING_EPSILON: + damping = rough_damping + angular_damp = damping + + +func enter_zone(zone: BallZone) -> void: + _zones.push_back(zone) + + if zone.water_hazard: + entered_water.emit() + + +func exit_zone(zone: BallZone) -> void: + _zones.erase(zone) diff --git a/src/player/physics_ball/iron_physics.tres b/src/player/physics_ball/iron_physics.tres new file mode 100644 index 0000000..3056424 --- /dev/null +++ b/src/player/physics_ball/iron_physics.tres @@ -0,0 +1,7 @@ +[gd_resource type="PhysicsMaterial" format=3 uid="uid://cfd56nhaods5a"] + +[resource] +friction = 0.8 +rough = true +bounce = 1.0 +absorbent = true diff --git a/src/player/physics_ball/normal_physics.tres b/src/player/physics_ball/normal_physics.tres new file mode 100644 index 0000000..55a1901 --- /dev/null +++ b/src/player/physics_ball/normal_physics.tres @@ -0,0 +1,5 @@ +[gd_resource type="PhysicsMaterial" format=3 uid="uid://3bih72l068ic"] + +[resource] +friction = 0.8 +bounce = 0.5 diff --git a/src/player/physics_ball/physics_ball.tscn b/src/player/physics_ball/physics_ball.tscn index 183a800..186fe3a 100644 --- a/src/player/physics_ball/physics_ball.tscn +++ b/src/player/physics_ball/physics_ball.tscn @@ -1,13 +1,10 @@ [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="PhysicsMaterial" uid="uid://3bih72l068ic" path="res://src/player/physics_ball/normal_physics.tres" id="1_l23pw"] [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"] -[sub_resource type="PhysicsMaterial" id="PhysicsMaterial_2gatw"] -friction = 0.8 -bounce = 0.5 - [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_xqofq"] albedo_texture = ExtResource("1_y3q5j") albedo_texture_force_srgb = true @@ -32,13 +29,15 @@ radius = 0.05 [node name="PhysicsBall" type="RigidBody3D"] mass = 0.05 -physics_material_override = SubResource("PhysicsMaterial_2gatw") +physics_material_override = ExtResource("1_l23pw") continuous_cd = true contact_monitor = true max_contacts_reported = 1 linear_damp_mode = 1 angular_damp_mode = 1 +angular_damp = 8.0 script = ExtResource("1_iwh2u") +iron_damping = 1e+07 [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 1c3ed22..d42d008 100644 --- a/src/player/shot_setup/shot_setup.gd +++ b/src/player/shot_setup/shot_setup.gd @@ -102,7 +102,7 @@ var _tracking_camera: OrbitalCamera @onready var curve_animation: AnimationPlayer = %CurveAnimation @onready var ball_point: Node3D = %BallPoint -@onready var physics_ball: RigidBody3D = %PhysicsBall +@onready var physics_ball: GameBall = %PhysicsBall @onready var drive_ref: RayCast3D = %DriveRef @onready var drive_arrow: Node3D = %DriveArrow @@ -269,6 +269,7 @@ func _on_club_change(new_club: Club.Type) -> void: wedge_arrow.hide() iron_arrow.hide() putt_arrow.hide() + physics_ball.iron_ball = false club_selector.value = new_club match new_club: Club.Type.DRIVER: @@ -290,6 +291,7 @@ func _on_club_change(new_club: Club.Type) -> void: # TODO shot_ref = iron_ref iron_arrow.show() + physics_ball.iron_ball = true character.hold_right(Club.catalog.debug_iron.get_model()) Club.Type.SPECIAL: # TODO diff --git a/src/player/shot_setup/shot_setup.tscn b/src/player/shot_setup/shot_setup.tscn index 55cc6b3..fd10bcb 100644 --- a/src/player/shot_setup/shot_setup.tscn +++ b/src/player/shot_setup/shot_setup.tscn @@ -641,8 +641,6 @@ 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 @@ -682,7 +680,7 @@ debug_shape_thickness = 4 [node name="IronRef" type="RayCast3D" parent="Direction"] unique_name_in_owner = true -transform = Transform3D(0.7, 0, 0, 0, 0.494975, -0.494975, 0, 0.494975, 0.494975, 0, 0.08, 0) +transform = Transform3D(0.7, 0, 0, 0, 0.449952, -0.536231, 0, 0.536231, 0.449952, 0, 0.08, 0) enabled = false target_position = Vector3(0, 0, -1) collision_mask = 0 @@ -750,7 +748,7 @@ loop_animation = 1 [node name="IronArrow" type="Node3D" parent="ArrowPivot/Arrow"] unique_name_in_owner = true -transform = Transform3D(0.7, 0, 0, 0, 0.494975, -0.494975, 0, 0.494975, 0.494975, 0, 0, 0) +transform = Transform3D(0.7, 0, 0, 0, 0.449952, -0.536231, 0, 0.536231, 0.449952, 0, 0, 0) visible = false [node name="ArrowMesh" parent="ArrowPivot/Arrow/IronArrow" instance=ExtResource("2_s70wl")] diff --git a/src/world/ball_zone/ball_zone.gd b/src/world/ball_zone/ball_zone.gd index 3efa4f0..c2e0093 100644 --- a/src/world/ball_zone/ball_zone.gd +++ b/src/world/ball_zone/ball_zone.gd @@ -1,6 +1,8 @@ class_name BallZone extends Area3D ## A spatial area that has an effect on balls inside it. +@export var terrain_angular_damping := 1.0 + @export var water_hazard := false @@ -9,20 +11,11 @@ func _ready() -> void: 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: if body is GameBall: - on_ball_entered(body as GameBall) + (body as GameBall).enter_zone(self) func _on_body_exited(body: Node3D) -> void: if body is GameBall: - on_ball_exited(body as GameBall) + (body as GameBall).exit_zone(self)