class_name VinePlatform extends StaticBody2D ## ===== 节点引用 ===== @onready var player_trigger: Area2D = %PlayerTriggerVolumn @onready var hook_trigger: Area2D = %HookAttractVolumn @onready var sprite: Sprite2D = $Sprite2D @onready var collision: CollisionShape2D = $CollisionShape2D ## ===== 配置 ===== ## 触发到消失的总时间(固定) @export var destroy_total_time: float = 2.0 ## 触发后多久开始抖动(可调) @export var shake_start_time: float = 1.0 ## 消失后多久恢复(再生时间) @export var respawn_time: float = 3.0 ## 抖动参数 @export var shake_x: float = 1.0 @export var shake_y: float = 1.0 @export var step_time: float = 0.034 ## ===== 状态机 ===== enum State { IDLE, TRIGGERED, DISAPPEARED } var _current_state: State = State.IDLE ## ===== 抖动控制 ===== var _shake_tween: Tween var _shake_origin_pos: Vector2 ## 防止重复触发 var _sequence_started := false func _ready() -> void: player_trigger.body_entered.connect(_on_player_entered) hook_trigger.body_entered.connect(_on_hook_hit) ## ============================== ## 状态切换 ## ============================== func change_state(new_state: State) -> void: if new_state == _current_state: return _current_state = new_state match new_state: State.IDLE: _enable_platform(true) State.TRIGGERED: _start_destroy_sequence() State.DISAPPEARED: _disappear_and_respawn() ## ============================== ## 触发入口 ## ============================== func _on_player_entered(body: Node) -> void: if body is Player: _trigger_platform() func _on_hook_hit(hit_pos: Vector2, hook: Hook) -> void: _trigger_platform() func _trigger_platform() -> void: if _sequence_started: return _sequence_started = true print("藤蔓平台触发:2秒后消失,再生时间:", respawn_time) change_state(State.TRIGGERED) ## ============================== ## 销毁流程:抖动 + 消失(非销毁) ## ============================== func _start_destroy_sequence() -> void: var shake_time: float = clampf(shake_start_time, 0.0, destroy_total_time) var remaining_time: float = destroy_total_time - shake_time # 前半段静止 if shake_time > 0.0: await get_tree().create_timer(shake_time).timeout # 后半段抖动 if remaining_time > 0.0: start_shaking() await get_tree().create_timer(remaining_time).timeout stop_shaking() # 进入消失状态 change_state(State.DISAPPEARED) ## ============================== ## 消失 + 再生 ## ============================== func _disappear_and_respawn() -> void: print("平台消失,等待再生...") # 关闭平台 _enable_platform(false) # 等待再生时间 await get_tree().create_timer(respawn_time).timeout print("平台恢复!") # 重置触发锁 _sequence_started = false # 回到初始状态 change_state(State.IDLE) ## ============================== ## 启用/禁用平台(关键) ## ============================== func _enable_platform(enable: bool) -> void: sprite.visible = enable collision.disabled = not enable player_trigger.monitoring = enable hook_trigger.monitoring = enable ## ============================== ## 抖动效果 ## ============================== func start_shaking() -> void: if _shake_tween and _shake_tween.is_running(): return _shake_origin_pos = sprite.position _shake_tween = create_tween() _shake_tween.set_loops() _shake_tween.set_trans(Tween.TRANS_SINE) _shake_tween.set_ease(Tween.EASE_IN_OUT) _shake_tween.tween_property(sprite, "position", _shake_origin_pos + Vector2(-shake_x, -shake_y), step_time) _shake_tween.tween_property(sprite, "position", _shake_origin_pos + Vector2(shake_x, shake_y), step_time) _shake_tween.tween_property(sprite, "position", _shake_origin_pos + Vector2(-shake_x, shake_y), step_time) _shake_tween.tween_property(sprite, "position", _shake_origin_pos + Vector2(shake_x, -shake_y), step_time) func stop_shaking() -> void: if _shake_tween: _shake_tween.kill() _shake_tween = null sprite.position = _shake_origin_pos