Godot_Bouncy_Ball_Prototype/Ball/ball.gd

63 lines
1.9 KiB
GDScript

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