In today's tutorial we will create a slingshot mechanism, to launcha a draggable object. As you may have already guessed, let's take a draggable example as a template to start, and modify it, to add slinsghot mechanics.

I'm not a designer, so we won't have some fancy slingshot graphics. Instead we will simply draw a vector, which will represent the force vector of slingshot. Simple as that.

Before we start, I wanted to mention that there are some differences from darggable example. In this slingshot project, the definition of mouse events will be defined outside of scope function. Although they could have stayed inside, but since the contents of these function grow, it will be easier to manage them as separate methods. Because of this, mouse joint and ground object became classes properties, so they could be accessible from all class methods (basically, I simply wrote "self." before them).

So let's start. Firstly, we will define starting point object, where we will store starting point of slingshot, and create shape object, which will draw the force vector of slingshot. All this inside the init function.

--save starting point
self.startpoint = {}
--we will draw slingshot using Shape object
self.slingshot = Shape.new()
self:addChild(self.slingshot)

Now let's define on mouse down handler, which additionally to creating mouse joint, will also store the strating point of slingshot

-- create a starting point for slingshot
function scene:onMouseDown(event)
	if(self.ball:hitTestPoint(event.x, event.y)) then
		local jointDef = b2.createMouseJointDef(self.ground, self.ball.body, event.x, event.y, 100000)
		self.mouseJoint = self.world:createJoint(jointDef)
		--save starting point
		self.startpoint.x = event.x;
		self.startpoint.y = event.y;
	end	
end

Now on mouse move, we will draw/redraw the force vector of slingshot:

-- update the representation of slingshot
function scene:onMouseMove(event)
	--check if slingshot is pulled up
	if self.mouseJoint ~= nil then
		self.mouseJoint:setTarget(event.x, event.y)
		--clear any previous slingshot
		self.slingshot:clear()
		--set styles
		self.slingshot:setLineStyle(5, 0xff0000, 1)
		--draw line
		self.slingshot:beginPath()
		self.slingshot:moveTo(self.startpoint.x, self.startpoint.y)
		self.slingshot:lineTo(event.x, event.y)
		self.slingshot:endPath()
	end
end

And last thing we will do is applying impulse with according vector to ball body. Additionally, there is a strength parameter, which we can use to adjust overstrength of slingshot.

-- launch the ball
function scene:onMouseUp(event)
	--check if slingshot is pulled up
	if self.mouseJoint ~= nil then
		self.world:destroyJoint(self.mouseJoint)
		self.mouseJoint = nil
		--clear slingshot respresentation
		self.slingshot:clear()
		--define strength of slingshot
		local strength = 1
		--calculate force vector based on strength 
		--and distance of pull
		local xVect = (self.startpoint.x-event.x)*strength
		local yVect = (self.startpoint.y-event.y)*strength
		--applye impulse to target
		self.ball.body:applyLinearImpulse(xVect, yVect, self.ball:getX(), self.ball:getY())
	end
end

And that's it. Here's an example of how it looks like:

And here's the example Gideros project of demonstarted slingshot.