Multi-terrain physics

This commit is contained in:
Rob Kelly 2024-11-12 20:03:05 -07:00
parent 5b56f9cd58
commit cd9a58a660
9 changed files with 90 additions and 26 deletions

View File

@ -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)

View File

@ -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]

View File

@ -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)

View File

@ -0,0 +1,7 @@
[gd_resource type="PhysicsMaterial" format=3 uid="uid://cfd56nhaods5a"]
[resource]
friction = 0.8
rough = true
bounce = 1.0
absorbent = true

View File

@ -0,0 +1,5 @@
[gd_resource type="PhysicsMaterial" format=3 uid="uid://3bih72l068ic"]
[resource]
friction = 0.8
bounce = 0.5

View File

@ -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")

View File

@ -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

View File

@ -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")]

View File

@ -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)