I'm trying to make a game where the player travels through a 2D world, carrying a chain that will be used to pick things up and interact with the environment. I'm still trying to get the chain to work, but the basic approach (chain adapted from this tutorial) is:
- Have a player that is a RigidBody2D
- Move the player using setappliedforce in physicsprocess
- Have a child node (of the player) called Chain, with a child RigidBody2D called ChainStart
- Build the rest of the chain by creating segments (also RigidBody2D) & attaching them together using PinJoint2D, starting at ChainStart
The collisions have been set so that the player/chain don't bump into each other.
Everything seems to work up until the point where the chain collides with the environment - at which point the segments can get "caught" and pull apart. I've tried adjusting the Bias property of PinJoint2D, but that approach has similar issues (the segments come apart and things "explode" a bit more).
Am I taking the right approach for my problem, using RigidBody2D and PinJoint2D? If so, what's the best way to keep the chain segments together? If not, is there another approach I should be considering?
Sample project/code/gifs
I created a small demo project to represent the issue, which can be found here.
And some gifs representing the issue.
Here's the relevant code from the demo project, starting with the chain creation:
func _ready():
var player = get_node("boat")
var chainStart = player.get_node("Chain").get_node("ChainStart")
var child
var parent = chainStart
for i in range (loops):
child = addLoop(parent, LOOP.instance(), 4) # a LOOP is a segment
addPin(parent, child)
parent = child
child = addLoop(parent, ANCHOR.instance(), 6) # ANCHOR is just the last segment
addPin(parent, child)
func addLoop(parent, loop, offset):
loop.position = parent.global_position
loop.position.y += offset
add_child(loop)
return loop
func addPin(parent, child):
var pin = PIN.instance()
pin.node_a = parent.get_path()
pin.node_b = child.get_path()
parent.add_child(pin)
And the player's movement:
func _physics_process(delta):
set_applied_force(Vector2(50, 0)) # move one direction for demo
Thanks!