Created
July 31, 2012 11:05
-
-
Save reefwing/3216208 to your computer and use it in GitHub Desktop.
Tutorial 11 - Physics 101
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
supportedOrientations(ANY) | |
function setup() | |
-- Physics Demo Metadata | |
version = 1.0 | |
saveProjectInfo("Description", "Physics v"..version) | |
saveProjectInfo("Author", "Reefwing Software") | |
saveProjectInfo("Date", "30th July 2012") | |
saveProjectInfo("Version", version) | |
print("Physics Demo v"..version.."\n") | |
-- Load the sprite you want to attach to your physics object | |
-- you want the sprite and the object to be roughly the same | |
-- size and shape. | |
img = readImage("Dropbox:Mine_64x64") | |
-- Create an instance of PhysicsDebugDraw(). You will need to copy | |
-- this tab from the Physics Lab project or duplicate the project | |
-- and make it a dependency to your project. We have modified the | |
-- code to allow you to make the ground invisible and attach a | |
-- sprite. A copy of the modified class is provided below. | |
physicsDraw = PhysicsDebugDraw() | |
physicsDraw.spriteImage = img | |
physicsDraw.staticVisible = false | |
-- These functions are from the Physics Lab example which we have | |
-- extracted and provided in the Physics file below. As our sprite | |
-- is circular we attach it to the circle sprite. | |
createGround() | |
createBox(WIDTH/2, 100, 30, 30) | |
createCircle(WIDTH/2 + 50, HEIGHT, 32) | |
createRandPoly(WIDTH/2 + 150, 120) | |
end | |
function draw() | |
-- This sets the background color to black | |
background(blackColor) | |
-- Draw Demo Physics objects | |
physicsDraw:draw() | |
end | |
function collide(contact) | |
-- Leave this function out if you don't want to show the red dots | |
-- which indicate the collision points. | |
physicsDraw:collide(contact) | |
end | |
function touched(touch) | |
-- Use this method to demonstrate the pointInRect() collision detection function | |
if touch.state == ENDED then | |
-- Create a random polygon wherever you tap the screen. | |
createRandPoly(touch.x, touch.y, 25, 25) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--# Physics | |
-- | |
-- Functions from the Physics Lab example project | |
-- courtesy of Two Lives Left | |
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 | |
physicsDraw: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 | |
physicsDraw: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 | |
physicsDraw: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 | |
physicsDraw:addBody(poly) | |
return poly | |
end | |
function cleanup() | |
clearOutput() | |
physicsDraw:clear() | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--# PhysicsDebugDraw | |
-- | |
-- Class extracted from the Physics Lab project. | |
-- courtesy of Two Lives Left | |
-- | |
-- Modified by Reefwing Software | |
-- Version 1.0 | |
PhysicsDebugDraw = class() | |
function PhysicsDebugDraw:init() | |
self.bodies = {} | |
self.joints = {} | |
self.touchMap = {} | |
self.contacts = {} | |
self.spriteImage = nil -- spriteImage parameter added | |
self.staticVisible = true -- used to make ground invisible if required. | |
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 | |
if self.staticVisible then | |
stroke(255,255,255,255) | |
else | |
stroke(0,0,0,0) | |
end | |
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(5.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(5.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 | |
if self.spriteImage == nil then | |
strokeWidth(5.0) | |
line(0,0,body.radius-3,0) | |
strokeWidth(2.5) | |
ellipse(0,0,body.radius*2) | |
else | |
sprite(self.spriteImage, 0, 0, body.radius*2) | |
end | |
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment