godot-plateformer/_props/trigger_fall_rock/trigger_fall_rock.gd

55 lines
1.5 KiB
GDScript3
Raw Normal View History

2025-12-29 14:36:00 +08:00
extends Node2D
@export var binded_rock: Rock
@export var binded_volumn: PlayerTriggerVolumn
var _rock : Rock
var _volumn : PlayerTriggerVolumn
func _ready() -> void:
_rock = binded_rock if binded_rock != null else _find_first_rock(self)
_volumn = binded_volumn if binded_volumn != null else _find_first_volumn(self)
if not _volumn or not _rock: return
_volumn.player_entered.connect(_on_rock_start_shake,CONNECT_ONE_SHOT)
func _on_rock_start_shake(player: Player) -> void:
if not _rock: return
_rock.start_shaking()
$Timer.start()
$Timer.timeout.connect(_on_rock_falling)
func _on_rock_falling() -> void:
_rock.stop_shaking()
_rock.start_falling()
## ================================
## 查找工具函数(强类型)
## ================================
func _find_first_rock(root: Node) -> Rock:
var found: Node = _find_first_child_matching(root, func(n: Node) -> bool: return n is Rock)
return found as Rock
func _find_first_volumn(root: Node) -> PlayerTriggerVolumn:
var found: Node = _find_first_child_matching(root, func(n: Node) -> bool: return n is PlayerTriggerVolumn)
return found as PlayerTriggerVolumn
func _find_first_child_matching(root: Node, predicate: Callable) -> Node:
for child: Node in root.get_children():
# predicate.call() 返回值在类型系统里可能是 Variant所以别用 := 推断
var ok: bool = bool(predicate.call(child))
if ok:
return child
var deeper: Node = _find_first_child_matching(child, predicate)
if deeper != null:
return deeper
return null