Files
hello-godot/scripts/laser_beam.gd
T

79 lines
2.1 KiB
GDScript

class_name LaserBeam
extends Node2D
## 直线激光束:从所在位置垂直向上延伸,被第一个命中的敌人截断,
## 对其造成持续伤害(dps)。视觉为核心线 + 外发光双层 Line2D。
var dps := 10.0
var width := 5.0
var color := Color(0.55, 0.9, 1.0)
var active := false
var _core: Line2D
var _glow: Line2D
var _acc := 0.0
var _t := 0.0
func _ready() -> void:
z_index = 5
_glow = Line2D.new()
_glow.width = width * 2.8
_glow.default_color = Color(color, 0.28)
_glow.points = [Vector2.ZERO, Vector2(0.0, -10.0)]
add_child(_glow)
_core = Line2D.new()
_core.width = width
_core.default_color = color
_core.points = [Vector2.ZERO, Vector2(0.0, -10.0)]
add_child(_core)
visible = false
## 从自身祖先中解析所属游戏的敌容器(避免多实例时全局组查找拿错容器)
func _get_enemies_container() -> Node2D:
var node := get_parent()
while node != null:
var candidate := node.get_node_or_null("Enemies")
if candidate != null:
return candidate as Node2D
node = node.get_parent()
return null
func _process(delta: float) -> void:
if not active:
if visible:
visible = false
return
visible = true
_t += delta
var muzzle := global_position
var hit_y := -40.0
var target: EnemyBase = null
var container := _get_enemies_container()
if container != null:
for enemy in container.get_children():
if enemy is EnemyBase and not (enemy as EnemyBase).dead:
var e := enemy as EnemyBase
if absf(e.global_position.x - muzzle.x) < e.hit_radius + width * 0.5:
# 光束向上:命中敌人底缘;若炮口已进入敌人范围则从炮口起算
var hy := minf(muzzle.y, e.global_position.y + e.hit_radius)
if hy >= hit_y:
hit_y = hy
target = e
var length := maxf(muzzle.y - hit_y, 0.0)
var pulse := 1.0 + 0.1 * sin(_t * 42.0)
_core.width = width * pulse
_glow.width = width * 2.8 * pulse
_core.points = [Vector2.ZERO, Vector2(0.0, -length)]
_glow.points = [Vector2.ZERO, Vector2(0.0, -length)]
if target != null and is_instance_valid(target):
_acc += dps * delta
if _acc >= 1.0:
var whole := int(_acc)
_acc -= float(whole)
target.apply_damage(whole)