How to use Joint2D to create a rope

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By hrtsrttr

I’m trying to create a ninja rope with grappling hook, and am struggling on how to correctly use the Joint2D nodes.

I’m creating instances of a Rope segment scene (just a RigidBody2D with a sprite and collision shape), then creating joints (I’m using DampedSpringJoint2D because I want the rope to be somewhat elastic, I’ve also tried with PinJoint2D but no luck) and adding the rope segments as node_a and node_b.

However, they behave wild and unpredictable and don’t seem to truly follow the constraints I’ve set (length, rest_length). I’ve experimented a bit with the code and now it’s fairly messy and I still don’t seem to understand how to add two bodies together with a joint. As you’ll see I’m only a beginning developer so any advice on how to correctly go about this is appreciated. Here is the relevant code:


extends Node2D

const rope = preload("Rope.tscn")
var rp_array = []
var joint_array = []
var rp_amount = 14
var rp_segment_length = 14
onready var pos_start = Vector2(200, 200)
var rp_anchor2 = Node2D

const staticbody = preload("staticbody.tscn")

func _ready():
    var rp_anchor = staticbody.instance()
    add_child(rp_anchor)
    rp_anchor.position = Vector2(pos_start.x - rp_segment_length, pos_start.y)
    var rp_previous = rp_anchor


for n in range(rp_amount):
	
	#Create rope segments
		 
	var rp_current = rope.instance()
	rp_array.append(rp_current)
	add_child(rp_current)
	rp_current.position = Vector2(pos_start.x  + rp_segment_length * n, pos_start.y)
	
	#Create joints 
	
	var joint_current = DampedSpringJoint2D.new()
	joint_current.position = Vector2(rp_current.position.x + (rp_segment_length/2), rp_current.position.y)
	rp_current.add_child(joint_current)
	joint_array.append(joint_current)
	joint_current.node_a = rp_previous.get_path()
	joint_current.node_b = rp_current.get_path()
	joint_current.length = 4
	joint_current.rest_length = 2
	joint_current.stiffness = 100
	joint_current.bias = 10
	joint_current.disable_collision = true	
	rp_previous = rp_current
	
rp_anchor2 = staticbody.instance()
add_child(rp_anchor2)
rp_anchor2.position = Vector2(pos_start.x + rp_segment_length * (rp_amount +1), pos_start.y)
var joint_last = DampedSpringJoint2D.new()
joint_last.length = 4
joint_last.rest_length = 2
rp_anchor2.add_child(joint_last)
var rp_last = rp_array.back()
joint_last.node_a = rp_last.get_path()
joint_last.node_b = rp_anchor2.get_path()

var joint_origin = joint_array[0]

I’m not sure what your current problem is and I don’t have time right now to check it, but I did something similar in a personal project a while back and maybe you can check and see if it helps you, here is the link. The rope like logic is all between the String.tscn and the scenes-characters/Puppet.gd. Hope it helps.

tastyshrimp | 2019-12-20 19:08