82 lines
2.9 KiB
GDScript
82 lines
2.9 KiB
GDScript
extends EnemyHurtbox
|
|
@export var broadth = 250
|
|
@export var move_dir = -1
|
|
@export var angular_speed = 0.25
|
|
var angle = 0.0 if move_dir == 1 else PI
|
|
|
|
@onready var segments : Array[Node] = $Segments.get_children()
|
|
@onready var segment_count = segments.size()
|
|
var dead = false
|
|
|
|
func _process(delta: float) -> void:
|
|
if dead: return
|
|
if not $RayCast2D2.has_overlapping_bodies():
|
|
position += 200 * delta * $EarthAligner.global_from_local(Vector2.DOWN)
|
|
var y = position.length()
|
|
var ratio = - move_dir * broadth / (2 * y)
|
|
var rot_angle = - 2 * asin(ratio)
|
|
angle -= TAU * delta * angular_speed * move_dir
|
|
if(angle > PI + abs(rot_angle) / 2 or angle < - abs(rot_angle) / 2):
|
|
angle = fmod(angle + PI, PI)
|
|
position = position.rotated(rot_angle)
|
|
if dead:
|
|
return
|
|
if(move_dir == 1 and angle < 1 or move_dir == -1 and angle > PI - 1):
|
|
$RayCast2D.global_position = position.rotated(rot_angle)
|
|
$RayCast2D.rotation = rot_angle
|
|
if(move_dir == 1 and angle < 0.5 or move_dir == -1 and angle > PI - 0.5):
|
|
if(not $RayCast2D.has_overlapping_bodies()):
|
|
move_dir *= -1
|
|
if dead:
|
|
return
|
|
for i in range(segment_count):
|
|
var segment_pos_data = calculate_segment_location_and_rotation(i)
|
|
if not is_instance_valid(segments[i]):
|
|
get_tree().get_root().print_tree_pretty()
|
|
segments[i].position = segment_pos_data.position
|
|
segments[i].rotation = segment_pos_data.rotation
|
|
|
|
func calculate_segment_location_and_rotation (i) -> Dictionary:
|
|
var aerial_end_location = Vector2.from_angle(-angle) * broadth
|
|
var gravicenter = (aerial_end_location + Vector2(0, -broadth) + Vector2.ZERO) / 3
|
|
var ax = gravicenter.x
|
|
var ay = gravicenter.y
|
|
var bx = aerial_end_location.x
|
|
var by = aerial_end_location.y
|
|
var cx = 0
|
|
var cy = 0
|
|
var d = 2 * (ax * (by - cy) + bx * (cy - ay) + cx * (ay - by))
|
|
var ux = ((ax * ax + ay * ay) * (by - cy) + (bx * bx + by * by) * (cy - ay) + (cx * cx + cy * cy) * (ay - by)) / d
|
|
var uy = ((ax * ax + ay * ay) * (cx - bx) + (bx * bx + by * by) * (ax - cx) + (cx * cx + cy * cy) * (bx - ax)) / d
|
|
var center = Vector2(ux, uy)
|
|
var radius = center.length()
|
|
var switch_arc_dir = false
|
|
if ux < 0:
|
|
switch_arc_dir = !switch_arc_dir
|
|
if center.angle() > 1:
|
|
switch_arc_dir = !switch_arc_dir
|
|
|
|
var angle1 = - PI + center.angle()
|
|
var angle2 = - PI + (center-aerial_end_location).angle()
|
|
if(switch_arc_dir):
|
|
angle1 += TAU
|
|
|
|
if radius < 10000000:
|
|
return {"position": center + radius * Vector2.from_angle((i * angle1 + (segment_count - 1 - i) * angle2)/(segment_count - 1)),
|
|
"rotation": (i * angle1 + (segment_count - 1 - i) * angle2)/ (segment_count - 1) + sign(ux) * PI/2}
|
|
|
|
else:
|
|
return {"position" : Vector2.UP * broadth * i / (segment_count - 1),
|
|
"rotation" : 3 * PI / 2}
|
|
|
|
func _on_damage_taken(_damage, _dir, _id):
|
|
$AudioStreamPlayer2D.play()
|
|
|
|
func _on_death():
|
|
dead = true
|
|
for child in get_children():
|
|
if not child is AudioStreamPlayer2D:
|
|
child.queue_free()
|
|
$AudioStreamPlayer2D.play()
|
|
await $AudioStreamPlayer2D.finished
|
|
queue_free()
|