Wasn't sure whether to post here or on SO so please move if needed.
I've been having a look into the box2D physics API provided by LOVE to try and create a swinging flail or weighted rope but I'm having some trouble keeping the jointed elements close together.
So far I've made a series of circular bodies and linked them together using revolute joints with the first element being static and the final element being slightly larger/heavier to act as a weight.
The code to generate each link is as follows:
for i = 1, segments, 1 do
link = {}
if (i == 1) then
link.body = love.physics.newBody(world, xpos, ypos, "static") --Starting link
else
link.body = love.physics.newBody(world, xpos, ypos, "dynamic")
end
if (i == segments) then
link.shape = love.physics.newCircleShape(endlink_radius) --Ending link
else
link.shape = love.physics.newCircleShape(link_radius)
end
link.fixture = love.physics.newFixture(link.body, link.shape) --Fix bodies to shapes
table.insert(chain,link)
ypos = ypos + link_distance --Place next link further down, keeping x position
end
And the code to join each link:
for i = 2, #chain, 1 do
x1,y1 = chain[i-1].body:getPosition() --First link position
x2,y2 = chain[i].body:getPosition() --Second link position
chain[i-1].join = love.physics.newRevoluteJoint(chain[i-1].body, chain[i].body, x1, y1, x2, y2, false ) --Join the two with a revolute joint
end
And this works quite well, producing a chain like this:
The next step is to move the chain, I'm currently moving the first static element and having it "drag" the rest of the links along with it using the following code:
position = vo.add(position, velocity) --Vector addition add velocity to current position to get new position
chain[1].body:setPosition(position.x, position.y) --Update the first link position
This works fine for slow speeds (chain currently moves towards mouse cursor) but any rapid movement causes everything to fall apart.
Is there anyway to easily keep the elements close together?
I've tried adjusting the weights and world gravity but couldn't see any difference, I've also thought about applying a force to each element when the first one moves but that doesn't seem quite right.
Thanks
Solution (Thanks to NauticalMile)
Change the previous position update:
position = vo.add(position, velocity) --Vector addition add velocity to current position to get new position
chain[1].body:setPosition(position.x, position.y) --Update the first link position
To a velocity update and have Box2D handle the movement:
chain[1].body:setLinearVelocity(velocity.x, velocity.y)