Skip to content

Instantly share code, notes, and snippets.

@royletron
Last active August 29, 2015 14:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save royletron/a9470c6081bc85faca28 to your computer and use it in GitHub Desktop.
Save royletron/a9470c6081bc85faca28 to your computer and use it in GitHub Desktop.
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment