Ball gets culled if velocity is low after rolling for a while

This commit is contained in:
Rob Kelly 2025-01-07 17:56:18 -07:00
parent 9bef191bda
commit dafd425359
4 changed files with 46 additions and 43 deletions

View File

@ -14,7 +14,6 @@ enum Type {
POWER,
}
const VELOCITY_SQ_EPSILON := 1e-4
const MAGNUS_SQ_EPSILON := 1e-3
## If enabled, ball ability cooldown is only reset at end of shot.
@ -23,6 +22,10 @@ const MAGNUS_SQ_EPSILON := 1e-3
## Material physics configuration for this ball.
@export var terrain_physics: TerrainPhysics
## Coefficient of the linear curve that determines the minimum speed at
## a given point in surface time below which the ball will be frozen.
@export var surface_cull_coefficient: float = 0.2
#@export var fluid_density := 1.225
#@export var lift_coefficient := 0.05
#@export var radius := 0.05
@ -116,6 +119,7 @@ func _integrate_forces(state: PhysicsDirectBodyState3D) -> void:
_position_on_last_wake = global_position
_last_contact_normal = Vector3.UP
_shot_time_s = 0.0
_surface_time_s = 0.0
# TODO something's fucky here... I think this gets called once after the ball sleeps
if state.get_contact_count():
@ -133,12 +137,19 @@ func _integrate_forces(state: PhysicsDirectBodyState3D) -> void:
primary_body = state.get_contact_collider_object(i)
_surface_terrain = Terrain.from_collision(global_position, primary_body)
_surface_time_s += state.step
var culling_speed_sq := pow(surface_cull_coefficient * _surface_time_s, 2) - 1
if linear_velocity.length_squared() < culling_speed_sq:
_manual_sleep()
else:
# Ball is in the air
_surface_terrain = Terrain.Type.NONE
_surface_time_s = 0.0
var params := terrain_physics.get_params(_surface_terrain)
angular_damp = params.angular_damp
linear_damp = params.linear_damp
func _physics_process(delta: float) -> void:
# Simulate magnus effect
@ -146,24 +157,9 @@ func _physics_process(delta: float) -> void:
if magnus.length_squared() > MAGNUS_SQ_EPSILON:
apply_central_force(magnus)
# Apply drag
var params := terrain_physics.get_params(_surface_terrain)
if linear_velocity.length() > params.linear_drag:
linear_velocity -= params.linear_drag * linear_velocity.normalized()
else:
linear_velocity = Vector3.ZERO
if angular_velocity.length() > params.angular_drag:
angular_velocity -= params.angular_drag * angular_velocity.normalized()
else:
angular_velocity = Vector3.ZERO
if linear_velocity.length_squared() < VELOCITY_SQ_EPSILON:
linear_velocity = Vector3.ZERO
if angular_velocity.length_squared() < VELOCITY_SQ_EPSILON:
angular_velocity = Vector3.ZERO
# Keep shot time
_shot_time_s += delta
_surface_time_s += delta
func enter_zone(zone: BallZone) -> void:
@ -194,11 +190,17 @@ func _on_sleeping_state_changed() -> void:
_awake = false
func _manual_sleep() -> void:
freeze = true
linear_velocity = Vector3.ZERO
angular_velocity = Vector3.ZERO
manual_sleep_timer.start()
func _on_collision(body: Node) -> void:
if is_sticky():
# Freeze physics as soon as we hit something
freeze = true
manual_sleep_timer.start()
_manual_sleep()
var terrain := Terrain.from_collision(global_position, body)
print_debug("Collision terrain: ", Terrain.Type.keys()[terrain])

View File

@ -19,53 +19,53 @@
[sub_resource type="Resource" id="Resource_casfi"]
script = ExtResource("4_onl6o")
linear_drag = 0.0
angular_drag = 1.0
linear_damp = 0.2
angular_damp = 0.0
[sub_resource type="Resource" id="Resource_3k63c"]
script = ExtResource("4_onl6o")
linear_drag = 0.0
angular_drag = 0.0
linear_damp = 0.0
angular_damp = 0.0
[sub_resource type="Resource" id="Resource_xf73q"]
script = ExtResource("4_onl6o")
linear_drag = 0.0
angular_drag = 1.0
linear_damp = 0.5
angular_damp = 0.0
[sub_resource type="Resource" id="Resource_nhn3l"]
script = ExtResource("4_onl6o")
linear_drag = 0.0
angular_drag = 1.0
linear_damp = 0.1
angular_damp = 0.0
[sub_resource type="Resource" id="Resource_m3wjo"]
script = ExtResource("4_onl6o")
linear_drag = 0.0
angular_drag = 1.0
linear_damp = 0.2
angular_damp = 0.0
[sub_resource type="Resource" id="Resource_h4rld"]
script = ExtResource("4_onl6o")
linear_drag = 0.0
angular_drag = 1.0
linear_damp = 0.1
angular_damp = 0.0
[sub_resource type="Resource" id="Resource_j6lib"]
script = ExtResource("4_onl6o")
linear_drag = 0.0
angular_drag = 1.0
linear_damp = 0.5
angular_damp = 0.0
[sub_resource type="Resource" id="Resource_7f7ql"]
script = ExtResource("4_onl6o")
linear_drag = 0.0
angular_drag = 3.0
linear_damp = 1.0
angular_damp = 0.0
[sub_resource type="Resource" id="Resource_pusmf"]
script = ExtResource("4_onl6o")
linear_drag = 1.0
angular_drag = 10.0
linear_damp = 4.0
angular_damp = 0.0
[sub_resource type="Resource" id="Resource_edkxb"]
script = ExtResource("4_onl6o")
linear_drag = 0.0
angular_drag = 1.0
linear_damp = 0.2
angular_damp = 0.0
[sub_resource type="Resource" id="Resource_3ngau"]
script = ExtResource("3_52hui")

View File

@ -1,5 +1,5 @@
class_name TerrainParameters extends Resource
## Physical parameters for an individual terrain type.
@export var linear_drag := 0.0
@export var angular_drag := 0.0
@export var linear_damp := 0.0
@export var angular_damp := 0.0

View File

@ -63,7 +63,8 @@ var _cached_vel: Vector3
func set_ball(ball: GameBall) -> void:
global_position = ball.global_position
linear_damp = ball.linear_damp
linear_damp = ball.terrain_physics.default.linear_damp
print("using linear damp: ", linear_damp)
func _process(_delta: float) -> void: