63 lines
1.9 KiB
GDScript3
63 lines
1.9 KiB
GDScript3
|
extends RigidBody3D
|
||
|
|
||
|
|
||
|
signal ball_collision_started
|
||
|
signal ball_collision_ended
|
||
|
|
||
|
var captured_velocity : Vector3
|
||
|
var bounced_velocity : Vector3
|
||
|
var just_collided = false
|
||
|
|
||
|
var total_bounce_duration = 0.5
|
||
|
var gravity = Vector3(0, -10, 0)
|
||
|
|
||
|
|
||
|
func _physics_process(delta):
|
||
|
# Capture the linear velocity unless the ball have stopped on collision
|
||
|
if not just_collided:
|
||
|
captured_velocity = linear_velocity
|
||
|
|
||
|
_get_collision(delta)
|
||
|
|
||
|
|
||
|
var collision_normal : Vector3
|
||
|
var collision_angle_factor : float
|
||
|
func _get_collision(delta):
|
||
|
var collision : KinematicCollision3D
|
||
|
# test_only is true so this function doesn't move the ball on top of the main movement
|
||
|
collision = move_and_collide(linear_velocity * delta, true)
|
||
|
|
||
|
# A collision happens
|
||
|
if collision:
|
||
|
# Get collision data stuff
|
||
|
collision_normal = collision.get_normal()
|
||
|
bounced_velocity = captured_velocity.bounce(collision_normal)
|
||
|
# Get the dot product between the surface normal and the ball direction on hit
|
||
|
collision_angle_factor = collision_normal.dot(captured_velocity.normalized() * -1)
|
||
|
|
||
|
# Set the duration of the timer based on the collision angle
|
||
|
$TimerCollision.wait_time = total_bounce_duration * collision_angle_factor
|
||
|
$TimerCollision.start()
|
||
|
|
||
|
# Send the signal after getting the data to avoid having zeroed values
|
||
|
just_collided = true
|
||
|
emit_signal("ball_collision_started")
|
||
|
|
||
|
# Completely stop the ball in place
|
||
|
linear_velocity = Vector3.ZERO
|
||
|
freeze = true
|
||
|
|
||
|
# Move the ball again after the timer runs out
|
||
|
# The if check prevents the timeout function from trying to connect every frame
|
||
|
if not $TimerCollision.timeout.is_connected(_after_collision):
|
||
|
$TimerCollision.timeout.connect(_after_collision)
|
||
|
|
||
|
|
||
|
func _after_collision():
|
||
|
just_collided = false
|
||
|
emit_signal("ball_collision_ended")
|
||
|
|
||
|
# Unfreezes the ball and apply the bounced captured velocity to it
|
||
|
freeze = false
|
||
|
linear_velocity = bounced_velocity
|