forked from kanium/starcheese
88 lines
2.5 KiB
GDScript3
88 lines
2.5 KiB
GDScript3
|
|
# Casts a laser along a raycast, emitting particles on the impact point.
|
||
|
|
# Use `is_casting` to make the laser fire and stop.
|
||
|
|
# You can attach it to a weapon or a ship; the laser will rotate with its parent.
|
||
|
|
extends RayCast2D
|
||
|
|
|
||
|
|
# Speed at which the laser extends when first fired, in pixels per seconds.
|
||
|
|
@export var cast_speed := 70000.0
|
||
|
|
# Maximum length of the laser in pixels.
|
||
|
|
@export var max_length := 1400.0
|
||
|
|
# Base duration of the tween animation in seconds.
|
||
|
|
@export var growth_time := 0.1
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
# If `true`, the laser is firing.
|
||
|
|
# It plays appearing and disappearing animations when it's not animating.
|
||
|
|
# See `appear()` and `disappear()` for more information.
|
||
|
|
var is_casting := false: set = set_is_casting
|
||
|
|
|
||
|
|
@onready var fill : Line2D = $FillLine2D
|
||
|
|
var tween : Tween
|
||
|
|
@onready var casting_particles := $CastingParticles2D
|
||
|
|
@onready var collision_particles := $CollisionParticles2D
|
||
|
|
@onready var beam_particles := $BeamParticles2D
|
||
|
|
|
||
|
|
@onready var line_width: float = fill.width
|
||
|
|
|
||
|
|
|
||
|
|
func _ready() -> void:
|
||
|
|
set_physics_process(false)
|
||
|
|
fill.points[1] = Vector2.ZERO
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
func _physics_process(delta: float) -> void:
|
||
|
|
target_position = (target_position + Vector2.RIGHT * cast_speed * delta).limit_length(max_length)
|
||
|
|
cast_beam()
|
||
|
|
|
||
|
|
|
||
|
|
func set_is_casting(cast: bool) -> void:
|
||
|
|
is_casting = cast
|
||
|
|
|
||
|
|
if is_casting:
|
||
|
|
target_position = Vector2.ZERO
|
||
|
|
fill.points[1] = target_position
|
||
|
|
appear()
|
||
|
|
else:
|
||
|
|
# Reset the laser endpoint
|
||
|
|
fill.points[1] = Vector2.ZERO
|
||
|
|
|
||
|
|
collision_particles.emitting = false
|
||
|
|
disappear()
|
||
|
|
|
||
|
|
set_physics_process(is_casting)
|
||
|
|
beam_particles.emitting = is_casting
|
||
|
|
casting_particles.emitting = is_casting
|
||
|
|
|
||
|
|
|
||
|
|
# Controls the emission of particles and extends the Line2D to `cast_to` or the ray's
|
||
|
|
# collision point, whichever is closest.
|
||
|
|
func cast_beam() -> void:
|
||
|
|
var cast_point := target_position
|
||
|
|
|
||
|
|
force_raycast_update()
|
||
|
|
collision_particles.emitting = is_colliding()
|
||
|
|
|
||
|
|
if is_colliding():
|
||
|
|
cast_point = to_local(get_collision_point())
|
||
|
|
collision_particles.global_rotation = get_collision_normal().angle()
|
||
|
|
collision_particles.position = cast_point
|
||
|
|
|
||
|
|
fill.points[1] = cast_point
|
||
|
|
beam_particles.position = cast_point * 0.5
|
||
|
|
beam_particles.process_material.emission_box_extents.x = cast_point.length() * 0.5
|
||
|
|
|
||
|
|
|
||
|
|
func appear() -> void:
|
||
|
|
if tween and tween.is_running():
|
||
|
|
tween.kill()
|
||
|
|
tween = create_tween()
|
||
|
|
tween.tween_property(fill, "width", line_width, growth_time * 2).from(0)
|
||
|
|
|
||
|
|
func disappear() -> void:
|
||
|
|
if tween and tween.is_running():
|
||
|
|
tween.kill()
|
||
|
|
tween = create_tween()
|
||
|
|
tween.tween_property(fill, "width", 0, growth_time).from_current()
|