Godot_Bouncy_Ball_Prototype/Ball/ball_meshes.gd

78 lines
2.5 KiB
GDScript

extends Node3D
@onready var skeleton_flying = $BallFlyingMesh.get_node("SKL_projectile_flying/Skeleton3D")
@onready var skeleton_bouncing = $BallBouncingMesh.get_node("SKL_projectile_bouncing/Skeleton3D")
@onready var ball = owner
@onready var timer = ball.get_node("TimerCollision")
var is_bouncing = false
var max_squish_xy = 0.5 # Starts at 0
var max_squish_z = 0.8 # From 0 to 1
# Apply a small offset to the up vector in the look_at function to fix it
# not working when the target is perfectly aligned with the up vector
const LOOK_AT_OFFSET_FIX = Vector3(0.01, 1, 0.01)
func _ready():
ball.ball_collision_started.connect(_on_collision)
ball.ball_collision_ended.connect(_after_collision)
func _process(delta):
_align_mesh_to_direction()
_squish_animation()
func _align_mesh_to_direction():
# Align the RotationNode to the movement direction
$RotationNode.look_at(ball.captured_velocity + ball.global_position, LOOK_AT_OFFSET_FIX)
# Convert the rotation euler into a quaternion
var euler_rotation = $RotationNode.rotation
var quaternion_rotation : Quaternion
quaternion_rotation = quaternion_rotation.from_euler(euler_rotation)
# Rotate the bone
skeleton_flying.set_bone_pose_rotation(1, quaternion_rotation)
func _on_collision():
$BallFlyingMesh.visible = false
$BallBouncingMesh.visible = true
is_bouncing = true
# Align the Meshes node to the surface normal so the bouncing mesh is properly aligned
look_at(ball.collision_normal + ball.global_position, LOOK_AT_OFFSET_FIX)
func _after_collision():
$BallFlyingMesh.visible = true
$BallBouncingMesh.visible = false
is_bouncing = false
# Reset the Meshes node rotation
rotation = Vector3.ZERO
func _squish_animation():
if is_bouncing:
# Remap the time_left value of the timer
var time_left_remap = remap(timer.time_left, timer.wait_time, 0, 0, 2)
var time_left_pingpong = pingpong(time_left_remap, 1)
# Multiply the scaling by the collision angle factor to reduce
# the squishing effect at shallow angles
var scale_xy_factor = 1.0 + (ball.collision_angle_factor * max_squish_xy)
var scale_xy = 1.0 * remap(time_left_pingpong, 0, 1, 1, scale_xy_factor)
var scale_z_factor = 1.0 - (ball.collision_angle_factor * max_squish_z)
var scale_z = 1.0 * remap(time_left_pingpong, 0, 1, 1, scale_z_factor)
# Compose the vector for the bone scaling
var scale_squish_vector = Vector3(scale_xy, scale_xy, scale_z)
# Scale the bone
skeleton_bouncing.set_bone_pose_scale(1, scale_squish_vector)