I was wandering around the physics example project and found it’s touch mechanism interesting, so I added it to this. Basically once touched the objects elastic towards wherever the initiating touch is, the force is applied to where you initially touched the object, and you can touch each end with a finger and control it’s rotation quite precisely.
supportedOrientations(LANDSCAPE_ANY)
function setup()
iparameter("linearFriction", 1, 100, 15)
iparameter("angularFriction", 1, 100, 15)
watch("bodies[1].body.angularVelocity")
physics.gravity(0,0)
walls = {
physics.body(EDGE, vec2(0, 0), vec2(WIDTH, 0)),
physics.body(EDGE, vec2(0, 0), vec2(0, HEIGHT)),
physics.body(EDGE, vec2(WIDTH, HEIGHT), vec2(WIDTH, 0)),
physics.body(EDGE, vec2(WIDTH, HEIGHT), vec2(0, HEIGHT)),
}
for k, v in ipairs(walls) do
v.restitution = .7
end
bodies = {}
for i = 1, 5 do
bodies[i] = Brick()
end
bodyTouches = {}
end
function draw()
background(0, 0, 0, 255)
processTouches()
for k, v in ipairs(bodies) do
applySurfaceFriction(v.body)
v:draw()
end
end
function processTouches()
strokeWidth(5)
stroke(128,0,128)
local gain = 100.0
local damp = 5
for k,v in pairs(bodyTouches) 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)
line(touchPoint.x, touchPoint.y, worldAnchor.x, worldAnchor.y)
end
end
function applySurfaceFriction(body)
--if it's slow, stop it dead
--movement friction
if body.linearVelocity:len() < linearFriction * 2 then
body.linearVelocity = vec2(0,0)
else
body.linearVelocity = body.linearVelocity - linearFriction * body.linearVelocity:normalize()
end
--spinning friction
if math.abs(body.angularVelocity) < angularFriction * 2 then
body.angularVelocity = 0
else
if body.angularVelocity > 0 then
body.angularVelocity = body.angularVelocity - angularFriction
else
body.angularVelocity = body.angularVelocity + angularFriction
end
end
end
function touched(touch)
local touchPoint = vec2(touch.x, touch.y)
if touch.state == BEGAN then
for k,v in ipairs(bodies) do
if v.body:testPoint(touchPoint) then
bodyTouches[touch.id] = {tp = touchPoint, body = v.body, anchor = v.body:getLocalPoint(touchPoint)}
end
end
end
if touch.state == ENDED then
if bodyTouches[touch.id] ~= nil then
bodyTouches[touch.id] = nil
end
end
if touch.state == MOVING then
if bodyTouches[touch.id] ~= nil then
bodyTouches[touch.id].tp = touchPoint
end
end
end
---------------
Brick = class()
function Brick:init()
self.width = 100
self.height = 50
self.colour = color(255, 0, 0, 255)
--self.body = physics.body(CIRCLE, 50)
self.body = physics.body(POLYGON, vec2(-self.width / 2, -self.height / 2),
vec2(-self.width / 2, self.height / 2), vec2(self.width / 2, self.height / 2),
vec2(self.width / 2, -self.height / 2))
self.body.position = vec2(math.random(WIDTH), math.random(HEIGHT))
self.body.density = 2
self.body.restitution = .7
--self.body.linearDamping = 0.9
--self.body.angularDamping = 0.9
end
function Brick:draw()
fill(self.colour)
--ellipse(self.body.x, self.body.y, 100)
pushMatrix()
translate(self.body.x, self.body.y)
rotate(self.body.angle)
rect(-self.width / 2, -self.height / 2, self.width, self.height)
popMatrix()
end