extends Area2D ## 激光。两种模式: ## - always_on = true(默认):**固定障碍** —— 一直亮着,碰到就扣血,只能绕开或用钥匙传送穿过去 ## - always_on = false:循环「蓄力闪烁 -> 发射 -> 熄灭」,需要卡时间通过 ## 光束从自己的原点沿 +X 方向伸出,想改朝向就转节点本身。 enum State { WAIT, WARMUP, FIRING } ## 固定障碍模式(一直亮着) @export var always_on: bool = true @export var length: float = 90.0 @export var thickness: float = 6.0 @export var damage: int = 1 ## 蓄力(闪烁警告)时长,只有循环模式用 @export var warmup: float = 0.8 ## 发射持续时长,只有循环模式用 @export var fire_time: float = 0.35 ## 两次发射之间的间隔,只有循环模式用 @export var cooldown: float = 1.8 ## 开场后第一次发射前的延迟,只有循环模式用 @export var start_delay: float = 1.0 @export var laser_color: Color = Color(1.0, 0.25, 0.25) @export var warn_color: Color = Color(1.0, 0.8, 0.4) var _state: int = State.WAIT var _timer: float = 0.0 var _first: bool = true var _beam: Polygon2D = null func _ready() -> void: add_to_group("hazard") _beam = get_node_or_null("Beam") as Polygon2D var half := thickness * 0.5 if _beam != null: _beam.polygon = PackedVector2Array([ Vector2(0.0, -half), Vector2(length, -half), Vector2(length, half), Vector2(0.0, half)]) _beam.color = laser_color _beam.visible = always_on var hit := get_node_or_null("HitBox") as CollisionShape2D if hit != null: var rect := RectangleShape2D.new() rect.size = Vector2(length, thickness) hit.shape = rect hit.position = Vector2(length * 0.5, 0.0) func _physics_process(delta: float) -> void: if always_on: if _beam != null: _beam.visible = true _beam.color = laser_color _hurt_overlaps() return _timer += delta match _state: State.WAIT: var wait: float = start_delay if _first else cooldown if _timer >= wait: _first = false _state = State.WARMUP _timer = 0.0 State.WARMUP: if _beam != null: _beam.color = warn_color _beam.visible = fmod(_timer, 0.16) < 0.08 if _timer >= warmup: _state = State.FIRING _timer = 0.0 if _beam != null: _beam.color = laser_color _beam.visible = true State.FIRING: _hurt_overlaps() if _timer >= fire_time: _state = State.WAIT _timer = 0.0 if _beam != null: _beam.visible = false ## 每帧检查压在光柱里的东西(不能只靠 body_entered, ## 因为玩家可能本来就在光柱里,那样不会触发 entered) func _hurt_overlaps() -> void: for body in get_overlapping_bodies(): if body.has_method("hurt"): body.hurt(damage)