64 lines
1.6 KiB
GDScript
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
|