## GiftBox — tap while closed to open: lid rises and fades out, gift inside fades in. class_name GiftBox extends Node2D enum State { CLOSED, OPENING, OPEN } const LID_OPEN_Y: float = -120.0 const OPEN_DURATION: float = 0.5 const GIFT_FADE_DURATION: float = 0.4 const BUTTON_HALF_WIDTH: float = 40.0 const BUTTON_HALF_HEIGHT: float = 50.0 var _state: State = State.CLOSED func _ready() -> void: var gift: Node2D = get_node_or_null("Gift") as Node2D if gift != null: gift.modulate.a = 0.0 func _input(event: InputEvent) -> void: if _state != State.CLOSED: return if not event is InputEventScreenTouch: return var touch: InputEventScreenTouch = event as InputEventScreenTouch if not touch.pressed: return var local: Vector2 = to_local(touch.position) if abs(local.x) > BUTTON_HALF_WIDTH or abs(local.y) > BUTTON_HALF_HEIGHT: return _start_opening() func _start_opening() -> void: _state = State.OPENING var lid: Node2D = get_node_or_null("Lid") as Node2D if lid == null: _state = State.OPEN return var tween: Tween = create_tween() tween.set_ease(Tween.EASE_OUT) tween.set_trans(Tween.TRANS_BACK) tween.tween_property(lid, "position:y", LID_OPEN_Y, OPEN_DURATION) tween.parallel().tween_property(lid, "modulate:a", 0.0, OPEN_DURATION) tween.finished.connect(_on_lid_opened) func _on_lid_opened() -> void: _state = State.OPEN var gift: Node2D = get_node_or_null("Gift") as Node2D if gift == null: return var tween: Tween = create_tween() tween.tween_property(gift, "modulate:a", 1.0, GIFT_FADE_DURATION)