This is an example of what can be done with the ROPE joint, searching for something similar to ContreJour game, check code and video:
http://www.youtube.com/watch?v=09ebtYBKquM
--# Main
supportedOrientations(LANDSCAPE_ANY)
displayMode(FULLSCREEN)
physics.resume()
-- Use this function to perform your initial setup
function setup()
ground = createGround(140)
rope = ElasticRope(WIDTH/2, HEIGHT/2-10)
player = createCircle(WIDTH/2, 179,21)
player.info = {name="player"}
-- walls
left = physics.body(EDGE, vec2(0,0), vec2(0,HEIGHT))
right= physics.body(EDGE, vec2(WIDTH,0), vec2(WIDTH, HEIGHT))
top = physics.body(EDGE, vec2(0,HEIGHT), vec2(WIDTH, HEIGHT))
end
function createCircle(x,y,r)
local circle = physics.body(CIRCLE, r)
-- enable smooth motion
circle.interpolate = true
circle.x = x
circle.y = y
circle.restitution = 0.25
return circle
end
function createBox(x,y,w,h)
-- polygons are defined by a series of points in counter-clockwise order
local box = physics.body(POLYGON, vec2(-w/2,h/2), vec2(-w/2,-h/2), vec2(w/2,-h/2), vec2(w/2,h/2))
box.interpolate = true
box.x = x
box.y = y
box.restitution = 0.25
return box
end
function createGround(height)
local ground = physics.body(POLYGON, vec2(0,height), vec2(0,0), vec2(WIDTH,0), vec2(WIDTH,height))
ground.type = STATIC
return ground
end
-- This function gets called once every frame
function draw()
-- This sets the background color to black
background(0, 0, 0)
--tint(142, 134, 134, 98)
sprite("SpaceCute:Background",WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)
noTint()
blendMode(ADDITIVE)
fill(161, 187, 188, 84)
noStroke()
rect(
ground.points[1].x, ground.points[1].y,
ground.points[4].x, ground.points[4].y/2
)
blendMode(NORMAL)
physics.gravity(Gravity)
rope:updateForces()
rope:draw()
pushMatrix()
translate(player.x, player.y)
rotate(player.angle)
sprite("Platformer Art:Battor Flap 2", 0,0,60)
popMatrix()
end
function touched(touch)
if rope:touched(touch) == false then
end
end
function collide(contact)
if contact.state == BEGAN and
contact.bodyA and contact.bodyA.info and contact.bodyA.info.name and
contact.bodyB and contact.bodyB.info and contact.bodyB.info.name
then
local na = contact.bodyA.info.name
local nb = contact.bodyB.info.name
if na == "ball" and nb=="player" then
ball = contact.bodyA
elseif nb == "ball" and na == "player" then
ball = contact.bodyB
end
if player and ball then
if #player.joints==0 and ball.info.dragged then
player.x = ball.x
player.y = ball.y
player.info.joint = physics.joint(
REVOLUTE, ball, player, ball.position, player.position
)
print("Attached")
end
end
end
end
--# ElasticRope
ElasticRope = class()
function ElasticRope:init(x,y)
self.touchMap= {}
self.touchBod= {}
self.touchBut= {}
self.joints = {}
self.base = createBox(x, y, 60, 80)
self.base.info = {
btnFunction = function()
-- dettach ball from base
if player.info.joint then
player.info.joint:destroy()
player.info.joint = nil
end
end
}
self.base.type = STATIC
self.ball = createCircle(self.base.x,self.base.y - 150, 30)
self.ball.density = 0.75
self.ball.info = {name = "ball", dragged = false}
self.ball.fixedRotation = true
self.ball.angularDamping = 0.1
self.rope = physics.joint(
ROPE, self.base, self.ball, self.base.position,
self.ball.position, 200
)
self.links = {}
local lc = 10
local len = (self.base.y - self.ball.y) / lc
local p = self.base.position - vec2(0, len/2)
local prev = self.base
for i = 1,lc do
local link = createBox(p.x, p.y, 5, len)
link.mask = {10}
local j = physics.joint(REVOLUTE, prev, link, p + vec2(0, len/2))
prev = link
table.insert(self.joints,j )
link.info = {joint = j} -- save joint to stay alive in the physics system
table.insert(self.links, link)
p.y = p.y - len
end
local j = physics.joint(REVOLUTE, prev, self.ball, self.ball.position)
prev.info = {joint = j}
-- add bodies to interactive touch maps
table.insert(self.touchBod, self.ball)
table.insert(self.touchBut, self.base)
end
function ElasticRope:draw()
--[[ if the base can be moved:
local gain = 250 * self.base.mass
local damp = 0.75
local vel = self.base.linearVelocity
self.base:applyForce(gain * self.dir - damp * vel)
self.base.linearDamping = vel:len() / 50
--]]
pushMatrix()
translate(self.base.x, self.base.y)
rotate(self.base.angle)
if player.info.joint then
sprite("Platformer Art:Block Special", 0, 0, 60)
else
sprite("Platformer Art:Block Special Brick", 0, 0, 60)
end
popMatrix()
pushMatrix()
translate(self.ball.x, self.ball.y)
rotate(self.ball.angle)
sprite("Platformer Art:Coin", 0, 0, self.ball.radius*2.5)
popMatrix()
tint(214, 149, 42, 255)
for k,v in ipairs(self.links) do
pushMatrix()
translate(v.x,v.y)
rotate(v.angle)
sprite("Space Art:Beam", 0,0,15,25)
popMatrix()
end
noTint()
end
function ElasticRope:touched(touch)
local touchPoint = vec2(touch.x, touch.y)
if touch.state == BEGAN then
-- first check buttons
for i,body in ipairs(self.touchBut) do
if body:testPoint(touchPoint) then
-- call button function
if body.info and body.info.btnFunction then
body.info.btnFunction()
return true
end
end
end
for i,body in ipairs(self.touchBod) do
if body.type == DYNAMIC and body:testPoint(touchPoint) then
body.info.dragged = true
self.touchMap[touch.id] = {
tp = touchPoint, body = body,
anchor = body:getLocalPoint(touchPoint)
}
return true
end
end
elseif touch.state == MOVING and self.touchMap[touch.id] then
self.touchMap[touch.id].tp = touchPoint
return true
elseif touch.state == ENDED and self.touchMap[touch.id] then
self.touchMap[touch.id].body.info.dragged = false
self.touchMap[touch.id] = nil
return true;
end
return false
end
function ElasticRope:updateForces()
local gain = 2.0
local damp = 0.5
for k,v in pairs(self.touchMap) do
local worldAnchor = v.body:getWorldPoint(v.anchor)
local touchPoint = v.tp
local diff = touchPoint - worldAnchor
local vel = v.body:getLinearVelocityFromWorldPoint(worldAnchor)
v.body:applyForce( (1/1) * diff * gain - vel * damp, worldAnchor)
end
end
function ElasticRope:hit(other, contact, first)
if contact.state == BEGAN then
local imp = math.max(0, (contact.normalImpulse-25) / 25)
if imp > 0.0 then
sound(SOUND_HIT, 47051, imp)
if other and other.damage then other:damage(imp) end
end
end
end
You have to catch the fly with the coin xD