Chains with pivot joint is not stable

Hi,

I created a chain by attaching squares with pivot joints, it is working as expected when the chain is attached to a static base.

But when i attach the chain to a falling base and suddenly stop a the falling base the chain attached to the base doesnt stop along with the base, the chain keeps extending like an elastic rope. how can i have a chain which acts like a solid rope without any elasticity.

please use the test case to better understand my problem

local physics = require( “physics” )

physics.start()

physics.setDrawMode(“hybrid”)

– physics.setContinuous( false )

physics.setVelocityIterations( 16 )

local function make_chain( x, y, w, h, c )

for i = 1, c do 

local link = display.newRect(  0,0,w, h )

link.x,link.y = x, y+(i*(h+1))

link:toBack( )

if (i == 1) then

firstChain = link

end

physics.addBody( link, “dynamic”, { friction=0, bounce=0 ,isSensor = true, density = 0 } )

link.gravityScale = 0

if i > 1 then 

print( i )

physics.newJoint( “pivot”, prev_link, link, x, prev_link.y + (h*.5) )

end 

prev_link = link

end 

end 

make_chain( display.contentCenterX, -display.contentHeight, 20, 20, display.contentHeight/20 )

local dummyCeiling = display.newRect( display.contentCenterX, firstChain.y, display.contentWidth, 40 )

dummyCeiling.y = firstChain.y

physics.addBody( dummyCeiling, “dynamic”, { friction=0, bounce=0 ,isSensor = true, density = 0 } )

physics.newJoint( “pivot”, firstChain, dummyCeiling, firstChain.x, firstChain.y  )

function enterFrame( event )

if (dummyCeiling.y > 30) then

dummyCeiling.y = 30

end

end

Runtime:addEventListener(“enterFrame”, enterFrame)

Hi @nischal.srinivas,

I did a little testing on your code. Instead of using a “dynamic” type for the ceiling, use “kinematic”. Also, remove the “.gravityScale=0” from the chain links. The “kinematic” ceiling will not be dragged down by the weight of the chain, nor will it fall under the force of gravity, because it will be immune to forces entirely.

To move the ceiling once it’s a kinematic object, you can still set its linear velocity directly, or just update its position during a Runtime event.

Hope this helps,

Brent 

Also, don’t forget Corona comes with a bunch of samples in the installation directory, including:

  • Corona SDK\Sample Code\Physics\Chains
  • Corona SDK\Sample Code\Physics\Bridge

Both should help.

Hi Brent,

Thanks for the quick reply,

I tried making the ceiling kinematic and moved it by setting linear velocity, but still im facing the same issue.

Please use the below testcase.

local physics = require( "physics" ) physics.start() physics.setDrawMode("hybrid") -- physics.setContinuous( false ) physics.setVelocityIterations( 16 ) local function make\_chain( x, y, w, h, c ) for i = 1, c do local link = display.newRect( 0,0,w, h ) link.x,link.y = x, y+(i\*(h+1)) link:toBack( ) if (i == 1) then firstChain = link end physics.addBody( link, "dynamic", { friction=0, bounce=0 ,isSensor = true, density = 0 } ) -- link.gravityScale = 0 if i \> 1 then print( i ) physics.newJoint( "pivot", prev\_link, link, x, prev\_link.y + (h\*.5) ) end prev\_link = link end end make\_chain( display.contentCenterX, -display.contentHeight, 20, 20, display.contentHeight/20 ) local dummyCeiling = display.newRect( display.contentCenterX, firstChain.y, display.contentWidth, 40 ) dummyCeiling.y = firstChain.y physics.addBody( dummyCeiling, "kinematic", { friction=0, bounce=0 ,isSensor = true, density = 0 } ) physics.newJoint( "pivot", firstChain, dummyCeiling, firstChain.x, firstChain.y ) dummyCeiling:setLinearVelocity( 0, 200 ) function enterFrame( event ) if (dummyCeiling.y \> 30) then dummyCeiling.y = 30 end end Runtime:addEventListener("enterFrame", enterFrame)

@Brent i did go through those example, but didnt find them useful for my case, both the examples show a chain attached to static objects

Hi again,

The issue in your example is that you’re not stopping the linear velocity of the ceiling when it reaches y > 30. You’re also not removing the Runtime listener at the same time. So effectively, you’re telling the ceiling that it still has linear velocity (downward) but then you’re resetting it to y=30 on every frame… this means you’re “fighting” what the physics engine wants to do, and you’re transferring all of that physical energy down through the chain. Just stop its linear velocity and turn off the Runtime updater, and the chain should remain intact.

Brent

Thanks Brent, ill try this and tell you if it worked

Hi @nischal.srinivas,

I did a little testing on your code. Instead of using a “dynamic” type for the ceiling, use “kinematic”. Also, remove the “.gravityScale=0” from the chain links. The “kinematic” ceiling will not be dragged down by the weight of the chain, nor will it fall under the force of gravity, because it will be immune to forces entirely.

To move the ceiling once it’s a kinematic object, you can still set its linear velocity directly, or just update its position during a Runtime event.

Hope this helps,

Brent 

Also, don’t forget Corona comes with a bunch of samples in the installation directory, including:

  • Corona SDK\Sample Code\Physics\Chains
  • Corona SDK\Sample Code\Physics\Bridge

Both should help.

Hi Brent,

Thanks for the quick reply,

I tried making the ceiling kinematic and moved it by setting linear velocity, but still im facing the same issue.

Please use the below testcase.

local physics = require( "physics" ) physics.start() physics.setDrawMode("hybrid") -- physics.setContinuous( false ) physics.setVelocityIterations( 16 ) local function make\_chain( x, y, w, h, c ) for i = 1, c do local link = display.newRect( 0,0,w, h ) link.x,link.y = x, y+(i\*(h+1)) link:toBack( ) if (i == 1) then firstChain = link end physics.addBody( link, "dynamic", { friction=0, bounce=0 ,isSensor = true, density = 0 } ) -- link.gravityScale = 0 if i \> 1 then print( i ) physics.newJoint( "pivot", prev\_link, link, x, prev\_link.y + (h\*.5) ) end prev\_link = link end end make\_chain( display.contentCenterX, -display.contentHeight, 20, 20, display.contentHeight/20 ) local dummyCeiling = display.newRect( display.contentCenterX, firstChain.y, display.contentWidth, 40 ) dummyCeiling.y = firstChain.y physics.addBody( dummyCeiling, "kinematic", { friction=0, bounce=0 ,isSensor = true, density = 0 } ) physics.newJoint( "pivot", firstChain, dummyCeiling, firstChain.x, firstChain.y ) dummyCeiling:setLinearVelocity( 0, 200 ) function enterFrame( event ) if (dummyCeiling.y \> 30) then dummyCeiling.y = 30 end end Runtime:addEventListener("enterFrame", enterFrame)

@Brent i did go through those example, but didnt find them useful for my case, both the examples show a chain attached to static objects

Hi again,

The issue in your example is that you’re not stopping the linear velocity of the ceiling when it reaches y > 30. You’re also not removing the Runtime listener at the same time. So effectively, you’re telling the ceiling that it still has linear velocity (downward) but then you’re resetting it to y=30 on every frame… this means you’re “fighting” what the physics engine wants to do, and you’re transferring all of that physical energy down through the chain. Just stop its linear velocity and turn off the Runtime updater, and the chain should remain intact.

Brent

Thanks Brent, ill try this and tell you if it worked