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, POWER,
} }
const VELOCITY_SQ_EPSILON := 1e-4
const MAGNUS_SQ_EPSILON := 1e-3 const MAGNUS_SQ_EPSILON := 1e-3
## If enabled, ball ability cooldown is only reset at end of shot. ## 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. ## Material physics configuration for this ball.
@export var terrain_physics: TerrainPhysics @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 fluid_density := 1.225
#@export var lift_coefficient := 0.05 #@export var lift_coefficient := 0.05
#@export var radius := 0.05 #@export var radius := 0.05
@ -116,6 +119,7 @@ func _integrate_forces(state: PhysicsDirectBodyState3D) -> void:
_position_on_last_wake = global_position _position_on_last_wake = global_position
_last_contact_normal = Vector3.UP _last_contact_normal = Vector3.UP
_shot_time_s = 0.0 _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 # TODO something's fucky here... I think this gets called once after the ball sleeps
if state.get_contact_count(): if state.get_contact_count():
@ -133,12 +137,19 @@ func _integrate_forces(state: PhysicsDirectBodyState3D) -> void:
primary_body = state.get_contact_collider_object(i) primary_body = state.get_contact_collider_object(i)
_surface_terrain = Terrain.from_collision(global_position, primary_body) _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: else:
# Ball is in the air # Ball is in the air
_surface_terrain = Terrain.Type.NONE _surface_terrain = Terrain.Type.NONE
_surface_time_s = 0.0 _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: func _physics_process(delta: float) -> void:
# Simulate magnus effect # Simulate magnus effect
@ -146,24 +157,9 @@ func _physics_process(delta: float) -> void:
if magnus.length_squared() > MAGNUS_SQ_EPSILON: if magnus.length_squared() > MAGNUS_SQ_EPSILON:
apply_central_force(magnus) 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 # Keep shot time
_shot_time_s += delta _shot_time_s += delta
_surface_time_s += delta
func enter_zone(zone: BallZone) -> void: func enter_zone(zone: BallZone) -> void:
@ -194,11 +190,17 @@ func _on_sleeping_state_changed() -> void:
_awake = false _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: func _on_collision(body: Node) -> void:
if is_sticky(): if is_sticky():
# Freeze physics as soon as we hit something # Freeze physics as soon as we hit something
freeze = true _manual_sleep()
manual_sleep_timer.start()
var terrain := Terrain.from_collision(global_position, body) var terrain := Terrain.from_collision(global_position, body)
print_debug("Collision terrain: ", Terrain.Type.keys()[terrain]) print_debug("Collision terrain: ", Terrain.Type.keys()[terrain])

View File

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

View File

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

View File

@ -63,7 +63,8 @@ var _cached_vel: Vector3
func set_ball(ball: GameBall) -> void: func set_ball(ball: GameBall) -> void:
global_position = ball.global_position 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: func _process(_delta: float) -> void: