78 lines
2.5 KiB
GDScript
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)
|
|
|