Instantly share code, notes, and snippets.

# royletron/Main.lua Last active Aug 29, 2015

WaterBob
 -- Water Bob -- Use this function to perform your initial setup local water local box function setup() print("alright let's do this!") debugDraw = PhysicsDebugDraw() createGround() box = createBox(WIDTH/2, 100, 30, 30) -- createCircle(WIDTH/2 + 50, 110, 30) -- createRandPoly(WIDTH/2 + 150, 120) water = Water(createBox(WIDTH/2, 50, WIDTH, 100)) camera = 0 end -- This function gets called once every frame function draw() -- This sets a dark background color background(40, 40, 50) -- Do your drawing here pushMatrix() camera = -box.x + WIDTH*0.5 translate(camera, 0) water:draw() debugDraw:draw() popMatrix() 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 circle.sleepingAllowed = false debugDraw:addBody(circle) 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.restitutions = 0.25 box.sleepingAllowed = false debugDraw:addBody(box) return box end function createGround() local ground = physics.body(POLYGON, vec2(0,20), vec2(0,0), vec2(WIDTH,0), vec2(WIDTH,20)) ground.type = STATIC debugDraw:addBody(ground) return ground end function createRandPoly(x,y) local count = math.random(3,10) local r = math.random(25,75) local a = 0 local d = 2 * math.pi / count local points = {} for i = 1,count do local v = vec2(r,0):rotate(a) + vec2(math.random(-10,10), math.random(-10,10)) a = a + d table.insert(points, v) end local poly = physics.body(POLYGON, unpack(points)) poly.x = x poly.y = y poly.sleepingAllowed = false poly.restitution = 0.25 debugDraw:addBody(poly) return poly end function touched(touch) if debugDraw:touched(touch) == false then -- currentTest:touched(touch) end end function collide(contact) if debugDraw then if contact.bodyA.sensor or contact.bodyB.sensor then water:collide(contact) end end end
 PhysicsDebugDraw = class() function PhysicsDebugDraw:init() self.bodies = {} self.joints = {} self.touchMap = {} self.contacts = {} end function PhysicsDebugDraw:addBody(body) table.insert(self.bodies,body) end function PhysicsDebugDraw:addJoint(joint) table.insert(self.joints,joint) end function PhysicsDebugDraw:clear() -- deactivate all bodies for i,body in ipairs(self.bodies) do body:destroy() end for i,joint in ipairs(self.joints) do joint:destroy() end self.bodies = {} self.joints = {} self.contacts = {} self.touchMap = {} end function PhysicsDebugDraw:draw() pushStyle() smooth() strokeWidth(5) stroke(128,0,128) 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) line(touchPoint.x, touchPoint.y, worldAnchor.x, worldAnchor.y) end stroke(0,255,0,255) strokeWidth(5) for k,joint in pairs(self.joints) do local a = joint.anchorA local b = joint.anchorB line(a.x,a.y,b.x,b.y) end stroke(255,255,255,255) noFill() for i,body in ipairs(self.bodies) do pushMatrix() translate(body.x, body.y) rotate(body.angle) if body.type == STATIC then stroke(255,255,255,255) elseif body.type == DYNAMIC then stroke(150,255,150,255) elseif body.type == KINEMATIC then stroke(150,150,255,255) end if body.shapeType == POLYGON then strokeWidth(3.0) local points = body.points for j = 1,#points do a = points[j] b = points[(j % #points)+1] line(a.x, a.y, b.x, b.y) end elseif body.shapeType == CHAIN or body.shapeType == EDGE then strokeWidth(3.0) local points = body.points for j = 1,#points-1 do a = points[j] b = points[j+1] line(a.x, a.y, b.x, b.y) end elseif body.shapeType == CIRCLE then strokeWidth(3.0) line(0,0,body.radius-3,0) ellipse(0,0,body.radius*2) end popMatrix() end stroke(255, 0, 0, 255) fill(255, 0, 0, 255) for k,v in pairs(self.contacts) do for m,n in ipairs(v.points) do ellipse(n.x, n.y, 10, 10) end end popStyle() end function PhysicsDebugDraw:touched(touch) local touchPoint = vec2(touch.x, touch.y) if touch.state == BEGAN then for i,body in ipairs(self.bodies) do if body.type == DYNAMIC and body:testPoint(touchPoint) then 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] = nil return true; end return false end function PhysicsDebugDraw:collide(contact) if contact.state == BEGAN then self.contacts[contact.id] = contact sound(SOUND_HIT, 2643) elseif contact.state == MOVING then self.contacts[contact.id] = contact elseif contact.state == ENDED then self.contacts[contact.id] = nil end end
 Water = class() function Water:init(body) -- you can accept and set parameters here self.body = body self.body.sensor = true self.body.type = STATIC -- self.body.restitution = -7 self.bodies = {} end function Water:draw() -- Codea does not automatically call this method for k,body in ipairs(self.bodies) do body:applyForce(vec2(0,20)) print(body.linearVelocity) end end function Water:touched(touch) -- Codea does not automatically call this method end function Water:add(body) table.insert(self.bodies, body) body.linearDamping = 3 body.angularDamping = 5 end function Water:remove(body) for k, b in ipairs(self.bodies) do if b == body then table.remove(self.bodies, k) break end end body.linearDamping = 0 body.angularDamping = 0 end function Water:collide(contact) if debugDraw then local body if contact.bodyA.sensor then body = contact.bodyB elseif contact.bodyB.sensor then body = contact.bodyA end if contact.state == BEGAN then self:add(body) elseif contact.state == ENDED then self:remove(body) end --[[ if contact.state == BEGAN then print("Sensor BEGAN") elseif contact.state == MOVING then print("Sensor MOVING") else print("Sensor ENDED") end end ]] end end