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)
Answer
Directly editing the position of a box2d body will produce non-physical behaviour, it's present because sometimes you will need to teleport bodies to a far away location, or reset the position of an object without the need to destroy/re-create it, etc... In your case the joints are not handling the position adjustments well.
The setPosition
function should not be used to advance the physics, box2d takes care of that all on its own when b2World:step
is called. In order for the chain to move smoothly, you just need to manipulated the top link in a different manner. I propose one of two suggestions:
- If the top link in the chain is supposed to be attached to something much bigger moving at a constant velocity, then I would recommend changing the
bodyType
of the top link to'kinematic'
using theBody:setType
function. Just initialize the velocity of the top link body to a reasonable value. This is demonstrated in RUBE:
- If you want the top link to have a dynamic behaviour, while still constraining it to only move along a given axis, you can create a 'dummy' static body, and connect the top link to the static body via a
PrismaticJoint
. Again, here's an example done in RUBE where I have applied a small force at the beginning using the MouseJoint:
In the real world objects accelerate when forces are applied to them. box2d functions in much the same way; enter the body:applyForce
function. You can use this to apply a force toward the cursor position. You can also add some LinearDamping
to the first or any of the links to make sure things don't get too out of hand.
Both of these options should be very stable, but let me know if there are any issues.
No comments:
Post a Comment