The_Dark_Side_of_Earth/enemies/leech.gd

96 lines
3.2 KiB
GDScript3
Raw Normal View History

2025-09-18 00:32:37 +02:00
extends Node2D
@export var broadth = 250
@export var move_dir = -1
2025-09-18 00:32:37 +02:00
@export var angular_speed = 0.25
@export var hp = 400
2025-09-18 00:32:37 +02:00
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 paused = false
var pause_time = 0.1
var iframes = 0.2
var iframe_time = 0
2025-09-18 00:32:37 +02:00
2025-09-18 18:10:44 +02:00
var check_grounded_delay = 8
func _ready() -> void:
for segment in segments:
segment.segment_damaged.connect(hurt)
func _physics_process(delta: float) -> void:
iframe_time = max(0, iframe_time - delta)
2025-09-18 00:32:37 +02:00
if not paused:
angle -= TAU * delta * angular_speed * move_dir
if(angle > PI or angle < 0):
paused = true
await get_tree().create_timer(pause_time).timeout
paused = false
angle = fmod(angle + PI, PI)
var y = position.length()
var ratio = - move_dir * broadth / (2 * y)
var rot_angle = - 2 * asin(ratio)
position = position.rotated(rot_angle)
if(move_dir == 1 and angle < 1 or move_dir == -1 and angle > PI - 1):
var y = position.length()
var ratio = - move_dir * broadth / (2 * y)
var rot_angle = - 2 * asin(ratio)
$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()):
paused = true
await get_tree().create_timer(pause_time).timeout
paused = false
move_dir *= -1
2025-09-18 00:32:37 +02:00
for i in range(segment_count):
var segment_pos_data = calculate_segment_location_and_rotation(i)
segments[i].position = segment_pos_data.position
segments[i].rotation = segment_pos_data.rotation
2025-09-18 18:10:44 +02:00
if check_grounded_delay > 0:
check_grounded_delay -= delta
elif not $RayCast2D2.has_overlapping_bodies():
queue_free()
2025-09-18 00:32:37 +02:00
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) + PI/2}
else:
return {"position" : Vector2.UP * broadth * i / (segment_count - 1),
"rotation" : 3 * PI / 2}
func hurt(damage : int, _dir):
if iframe_time <= 0:
hp -= damage
if(hp<=0):
queue_free()
else:
iframe_time = iframes