godot-plateformer/_props/vine_platform/vine_platform.gd

177 lines
4.0 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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