Ease hand intro tween

- replace fixed-duration parallel tween with a tween_method driving a single progress value
- button lights now trigger against the eased curve instead of delays
This commit is contained in:
Jennie Robinson Faber 2026-05-17 13:57:29 +01:00
parent b499825560
commit c14312c81e
2 changed files with 30 additions and 7 deletions

View file

@ -80,3 +80,5 @@ script = ExtResource("14_muzak_s")
[node name="TitleScreen" parent="." unique_id=1656317143 instance=ExtResource("11_title")] [node name="TitleScreen" parent="." unique_id=1656317143 instance=ExtResource("11_title")]
[node name="PauseMenu" parent="." unique_id=1244164419 instance=ExtResource("12_pause")] [node name="PauseMenu" parent="." unique_id=1244164419 instance=ExtResource("12_pause")]
[editable path="World"]

View file

@ -1,6 +1,10 @@
extends Sprite3D extends Sprite3D
const INTRO_DURATION := 1.5 # we easin' now
@export var intro_duration: float = 0.9
@export var intro_trans: Tween.TransitionType = Tween.TRANS_SINE
@export var intro_ease: Tween.EaseType = Tween.EASE_IN_OUT
const ENTRY_OFFSET := 0.5 const ENTRY_OFFSET := 0.5
const EXIT_OFFSET := 0.5 const EXIT_OFFSET := 0.5
const FORWARD_OFFSET := 0.05 const FORWARD_OFFSET := 0.05
@ -11,6 +15,10 @@ const FINGER_OFFSET_X := 0.0
var _buttons: Array = [] var _buttons: Array = []
var _intro_playing := false var _intro_playing := false
var _sprite_half_h := 0.0 var _sprite_half_h := 0.0
var _intro_sprite_start_y := 0.0
var _intro_sprite_end_y := 0.0
var _intro_button_thresholds: Array = []
var _intro_button_lit: Array = []
func _ready() -> void: func _ready() -> void:
visible = false visible = false
@ -78,23 +86,36 @@ func _play_intro() -> void:
global_position = Vector3(hand_x, sprite_start_y, hand_z) global_position = Vector3(hand_x, sprite_start_y, hand_z)
visible = true visible = true
var tween := create_tween().set_parallel(true) # now we have to do some more mathin' due to *easing*
tween.tween_property(self, "global_position:y", sprite_end_y, INTRO_DURATION) _intro_sprite_start_y = sprite_start_y
_intro_sprite_end_y = sprite_end_y
_intro_button_thresholds.clear()
_intro_button_lit.clear()
for i in range(_buttons.size()): for i in range(_buttons.size()):
var button_y_world = _buttons[i].global_position.y var button_y_world = _buttons[i].global_position.y
# weird thing: button_y is projected onto the hand's Z-plane to account for perspective # weird thing: button_y is projected onto the hand's Z-plane to account for perspective
# to keep the fingertip visually aligned with each button at the exact right moment # to keep the fingertip visually aligned with each button at the exact right moment
# thanks godot forums!
var button_y_proj = camera_pos.y + (button_y_world - camera_pos.y) * z_ratio var button_y_proj = camera_pos.y + (button_y_world - camera_pos.y) * z_ratio
var t_fraction = (finger_start_y - button_y_proj) / (finger_start_y - finger_end_y) var t_fraction = (finger_start_y - button_y_proj) / (finger_start_y - finger_end_y)
t_fraction = clamp(t_fraction, 0.0, 1.0) _intro_button_thresholds.append(clamp(t_fraction, 0.0, 1.0))
tween.tween_callback(_light_button.bind(i)).set_delay(t_fraction * INTRO_DURATION) _intro_button_lit.append(false)
var tween := create_tween()
tween.tween_method(_update_intro_progress, 0.0, 1.0, intro_duration).set_trans(intro_trans).set_ease(intro_ease)
await tween.finished await tween.finished
visible = false visible = false
_intro_playing = false _intro_playing = false
EventBus.intro_finished.emit() EventBus.intro_finished.emit()
func _update_intro_progress(progress: float) -> void:
global_position.y = lerp(_intro_sprite_start_y, _intro_sprite_end_y, progress)
for i in range(_buttons.size()):
if not _intro_button_lit[i] and progress >= _intro_button_thresholds[i]:
_intro_button_lit[i] = true
_light_button(i)
func _light_button(index: int) -> void: func _light_button(index: int) -> void:
var sprite: Sprite3D = _buttons[index].get_node("ButtonSprite") var sprite: Sprite3D = _buttons[index].get_node("ButtonSprite")
sprite.frame = index + 10 sprite.frame = index + 10