Shows how to incorporate verlet into box2D physics, could be used for a game.
--# Main
-- Trampoline
-- Use this function to perform your initial setup
function setup()
strings = {}
for i=1,1 do
strings[i] = Rope(vec2(0,100*-i+600),vec2(WIDTH-0,100*-i+600),50)
end
parameter.watch("1/DeltaTime")
ball = physics.body(CIRCLE,60)
ball.position = vec2(WIDTH/2,HEIGHT*0.8)
ball.restitution = 0.9
walls = physics.body(CHAIN,true,vec2(0,0),vec2(WIDTH,0),vec2(WIDTH,HEIGHT),vec2(0,HEIGHT))
end
function angleOfPoint(pnt)
return math.atan2(pnt.y,pnt.x)
end
function touched(t)
ball.position = vec2(t.x,t.y)
if t.state == MOVING then
ball.linearVelocity = vec2(t.deltaX,t.deltaY)*20
end
end
-- This function gets called once every frame
function draw()
-- This sets a dark background color
background(40, 40, 50)
-- This sets the line thickness
strokeWidth(5)
ellipse(ball.x,ball.y,ball.radius*2)
--ball.radius = ball.linearVelocity:len()*0.01+40
-- Do your drawing here
for k,v in pairs(strings) do
v:draw()
end
end
--# Rope
Rope = class()
function Rope:init(pos1,pos2,segamnt)
-- you can accept and set parameters here
self.joint = joint
self.p1 = pos1
self.p2 = pos2
self.m = mesh()
self.m.texture = readImage("Documents:gradbar")
self.r = {}
self.dst = pos1:dist(pos2)
self.segamnt = segamnt
self.prevnt = DeltaTime
self.seglen = (self.dst/segamnt)*0.7
self.segtbl = {}
for i=1,segamnt do
self.segtbl[i] = {}
self.segtbl[i].pos = pos1+(pos2-pos1):normalize()*self.seglen*i
self.segtbl[i].prev = self.segtbl[i].pos
self.segtbl[i].next = self.segtbl[i].pos +vec2(0,-5)
self.segtbl[i].ang = 0
self.r[i] = self.m:addRect(self.segtbl[i].pos.x,self.segtbl[i].pos.y,5,self.seglen)
end
self.r[segamnt+1] = self.m:addRect(self.p2.x,self.p2.y,5,self.seglen)
self.i = 0
end
function Rope:draw()
local p,dpos,len,va,da,ea,vb,db,eb,grav,stiffness,dt,nt,np,delta
local vd,vdl,diff
grav,stiffness,nt = vec2(0,0.01),0.01,DeltaTime
local segamnt = self.segamnt
local segtbl = self.segtbl
local maxl = self.seglen
local prevpos = vec2()
local nextpos = vec2()
local pos = vec2()
local segi = nil
for d=1,4 do
for i=1,segamnt do
segi = segtbl[i]
pos = segi.pos
if i==1 then
prevpos = self.p1
nextpos = segtbl[i+1].pos
elseif i==segamnt then
prevpos = segtbl[i-1].pos
nextpos = self.p2
else
prevpos = segtbl[i-1].pos
nextpos = segtbl[i+1].pos
end
if not pos or not prevpos or not nextpos then level.ropes:removeRope(self.id) return end
va = (pos+grav-prevpos)
da = (maxl-va:len())/va:len()
ea = va:len()-maxl
vb = (pos+grav-nextpos)
db = (maxl-vb:len())/vb:len()
eb = vb:len()-maxl
dt = (va*stiffness*da+vb*stiffness*db)
if dt:len() > 0 then
np = (pos-segtbl[i].prev) *(nt/self.prevnt) +(dt)*nt
segi.pos = segi.pos + np
end
if i == segamnt then
vd = self.p2-segi.pos
vdl = vd:len()
diff = vdl-maxl
vd = vd:normalize()
if vd:len()>0 then
segtbl[i].pos = segtbl[i].pos + vd*diff*0.5
end
end
if i > 1 then
vd = segtbl[i].pos-segtbl[i-1].pos
vdl = vd:len()
diff = vdl-maxl
vd = vd:normalize()
if vd:len()>0 then
segi.pos = segi.pos - vd*diff*0.5
segtbl[i-1].pos = segtbl[i-1].pos + vd*diff*0.5
end
elseif i==1 then
vd = segi.pos-self.p1
vdl = vd:len()
diff = vdl-maxl
vd = vd:normalize()
if vd:len()>0 then
segi.pos = segi.pos - vd*diff*0.5
end
end
segi.prev = pos+grav
pos = segi.pos
if ball:testPoint(pos) then
local dir = pos-ball.position
self.segtbl[i].pos = self.segtbl[i].pos+dir:normalize()*(ball.radius-dir:len())
ball:applyForce(-dir:normalize()*(ball.radius-dir:len())*10-ball.linearVelocity/60,self.segtbl[i].pos)
end
self.prevnt = DeltaTime
segtbl[i].ang = angleOfPoint(pos-prevpos)+math.pi/2
dpos = (prevpos+pos)/2
len = (prevpos:dist(pos))
self.m:setRect(self.r[i],dpos.x,dpos.y,5,len,segtbl[i].ang)
end
self.segtbl = segtbl
p = segtbl[segamnt].pos
dpos = p
len = (p:dist(self.p2))
self.m:setRect(self.r[segamnt+1],dpos.x,dpos.y,5,len,math.rad(angleOfPoint(p-self.p2))+math.pi/2)
end
self.m:draw()
end
Enjoy!