netmasked/scripts/cable.gd

64 lines
1.6 KiB
GDScript

@tool
extends Line2D
@export_group("Targets")
@export var target_a: Node2D
@export var target_b: Node2D
@export_group("Cable Settings")
@export var segment_count: int = 20
@export var rope_length: float = 300.0
@export var gravity: Vector2 = Vector2(0, 9.8)
@export var iterations: int = 5
var points_pos: Array[Vector2] = []
var points_prev: Array[Vector2] = []
var segment_dist: float
func _ready():
segment_dist = rope_length / segment_count
var start_pos = target_a.global_position if target_a else global_position
for i in range(segment_count):
points_pos.append(start_pos)
points_prev.append(start_pos)
points = PackedVector2Array(points_pos)
func _physics_process(delta: float):
if not target_a or not target_b:
return
_update_points(delta)
for i in range(iterations):
_apply_constraints()
var local_points = PackedVector2Array()
for p in points_pos:
local_points.append(to_local(p))
points = local_points
func _update_points(delta: float):
for i in range(segment_count):
var velocity = points_pos[i] - points_prev[i]
points_prev[i] = points_pos[i]
points_pos[i] += velocity + gravity * delta * 50.0
func _apply_constraints():
points_pos[0] = target_a.global_position
points_pos[segment_count - 1] = target_b.global_position
for i in range(segment_count - 1):
var p1 = points_pos[i]
var p2 = points_pos[i+1]
var diff = p1 - p2
var distance = diff.length()
var error = distance - segment_dist
var percent = error / distance
var offset = diff * percent * 0.5
if i != 0:
points_pos[i] -= offset
if i + 1 != segment_count - 1:
points_pos[i+1] += offset