In this example we will try to create chains and elastic ropes in Gideros using Box2D library.

So let's start with the easy one - the chains. If you image links in the chain, then they are not elastic and can rotate relatively to each other up to some point.

So what will do here is take draggable example project and add a chain method to it.

Method will aceept x and y coordinates where chain starts, the radius of each chain link and amount links in the chain. So we will simply iterate through amount of links, create new circle body for each link and join with the previous one using revolute joints.























function scene:chain(x, y, radius, amount)

	--create and store circle shape
	local shape = b2.CircleShape.new(0, 0, radius)
	
	-- and our fixture definition
	local fixtureDef = {shape = shape, density = 1.0, friction = 1, restitution = 0.3}
	
	--create empty box2d body for starting joint
	local ground = self.world:createBody({})
	
	-- start to create the chain
	local prevBody = ground
	
	for i=0,amount-1 do
		--calculate x and y coordinate
		local newX = x
		local newY = y + i*radius
		--create body
		local bodyDef = {type = b2.DYNAMIC_BODY, position = {x = newX, y = newY}, allowSleep = false}
		local body = self.world:createBody(bodyDef)
		body:createFixture(fixtureDef)

		--create image representing body
		local bitmap = Bitmap.new(Texture.new("ball.png"))
		bitmap:setAnchorPoint(0.5, 0.5)
		bitmap:setScale((radius*2)/bitmap:getWidth())
		bitmap:setPosition(body:getPosition())
		self:addChild(bitmap)
		
		bitmap.body = body
		
		-- attach each pair of chain elements with revolute joint
		local jointDef = b2.createRevoluteJointDef(prevBody, body, newX, newY)
		local revoluteJoint = self.world:createJoint(jointDef)
		revoluteJoint:setMaxMotorTorque(1)
		revoluteJoint:enableMotor(true)
	
		prevBody = body
	end
end

Then inside init method we simply call it as:





















self:chain(400,100, 20, 10)

And here is the result:

Since we are generating coordinates for each chain link dynamically, of course you might have question how can I create chain in a specific angle. So let's try to implement an option to provide an angle for a chain.

Hence our chain method will now accept another argument rotation, and we will calculate new x and y coordinates in chain method like this:

















local newax = ((-1 * math.sin(rotation))*(radius*i))
local neway = (math.cos(rotation) * (radius * i))
local newX = x + newax
local newY = y + neway

Now let's try to attach the ball to the end of the chain. For that we need the reference to last link in chain, which we can get from chain method by simply returning prevBody variable after loop.

Then inside init method we can attach ball body to last link in chain:















local lastLink = self:chain(400,100, 20, 10, 0)
local x, y = lastLink:getPosition()
--create ball
self.ball = self:ball(x, y)
local jointDef = b2.createRevoluteJointDef(self.ball.body, lastLink, x, y)
local revoluteJoint = self.world:createJoint(jointDef)
revoluteJoint:setMaxMotorTorque(1)
revoluteJoint:enableMotor(true)

And here is the result:

Now let's try to make the chain more elastic, to simulate a rubber rope. For that we will need to substitute revolute joint with a wheel joint and experiment a little with frequency and dampening.

So inside the loop in chain method, replace creating revolute joint with this code











-- attach each pair of bridge elements with wheel joint
local jointDef = b2.createWheelJointDef(prevBody, body, newX, newY, 1,1)
local wheelJoint = self.world:createJoint(jointDef)
wheelJoint:setSpringFrequencyHz(6)
wheelJoint:setSpringDampingRatio(1)

And here is the result:

And last thing we can try is to attach other end of chain not too the ball but to the world "ground" body to create a real physics slingshot.

Inside init method let's comment out the code which attaches ball to link chain and insted use this one:







local jointDef = b2.createWheelJointDef(lastLink, ground, x, y, 1,1)
local wheelJoint = self.world:createJoint(jointDef)
wheelJoint:setSpringFrequencyHz(6)
wheelJoint:setSpringDampingRatio(1)

Which gives us this result:

Here is the resulting project from this tutorial, now go and make some nice prototype from it ;)