Created
September 5, 2013 06:25
-
-
Save dermotbalson/6446670 to your computer and use it in GitHub Desktop.
Puzzle
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
--# Main | |
-- Main | |
--This is a simulation of an old puzzle game | |
--where you have a flat plastic surface with balls that roll around on it | |
--there are little holes you have to get the balls into by tipping the puzzle to roll the balls | |
--but there are obstacles, and if you tip too far, the balls come out again | |
--in this version, we'll start to build the puzzle, and when we add more than one ball, we'll | |
--start using physics to manage the ball collisions | |
--this project also uses the built in accelerometer, so tipping the iPad will roll the balls. | |
--HOW TO USE THIS PROJECT | |
--There are a number of tabs at the top. Press on a tab to see its code. | |
--Work through the tabs from left to right, to see the project develop | |
--You can run the code in any of the project tabs, by | |
--1. running the program, and | |
--2. selecting the tab number in the slider control at the upper left of the screen | |
--So if you want to run the code in Slots5, run the program, then move the slider control to 5 | |
--and the code in Slots5 should run | |
--The program will remember your selection after that. | |
--This enables you to work with one tab at a time, make changes and see the effects by running the program | |
--DO NOT TOUCH the lines below,they help manage the code tabs | |
tabs={} f="" | |
for i=1,10 do f=f.."s"..i.."={} table.insert(tabs,s"..i..") " end | |
ff=loadstring(f) ff() ff=nil f=nil | |
--This code manages which Code tab is run | |
--it remembers your last choice, and if you select a different one, it runs that instead | |
function setup() | |
LastCode=readProjectData("Code") or 1 | |
parameter.integer("Choose_a_tab",1,#tabs,LastCode,RunCode) | |
end | |
function RunCode() | |
output.clear() | |
saveProjectData("Code",Choose_a_tab) | |
print("CODE "..Choose_a_tab) | |
if s and s.Cleanup then s.Cleanup() end | |
s=tabs[Choose_a_tab] | |
s.setup() | |
end | |
function draw() | |
s.draw() | |
end | |
--# Slots1 | |
--Slots1 | |
--draw one slot | |
function s1.setup() | |
--nothing to do here yet | |
print("create a round slot for our ball to 'fall into'") | |
end | |
function s1.draw() | |
background(151, 190, 215, 255) | |
--draw round slot that balls will fall into | |
--draw two filled circles | |
--to create an illusion of a shadow | |
--the darker circle is offset by two pixels | |
pushStyle() | |
--darker (shadow) circle drawn behind | |
fill(78, 125, 148, 255) | |
ellipse(WIDTH/2,HEIGHT/2,50) | |
--draw slot, with a one pixel border | |
strokeWidth(1) | |
stroke(122, 152, 164, 255) --border colour | |
fill(143, 182, 198, 255) --fill colour | |
ellipse(WIDTH/2-2,HEIGHT/2+2,50) --put in middle of the screen just for now | |
popStyle() | |
end | |
--# Slots2 | |
--Slots2 | |
--draw four slots in the corners of the screen | |
function s2.setup() | |
--put all the slot making code in a function so we can keep things tidy | |
s2.SetupSlots() | |
print("now draw four slots") | |
end | |
function s2.SetupSlots() | |
--set up one in each corner of the screen | |
slotsX={} --table to hold x pos | |
slotsY={} --table to hold y pos | |
offset=200 | |
slotsX[1]=offset slotsY[1]=HEIGHT-offset --top left | |
slotsX[2]=WIDTH-offset slotsY[2]=HEIGHT-offset --top right | |
slotsX[3]=offset slotsY[3]=offset --bottom left | |
slotsX[4]=WIDTH-offset slotsY[4]=offset --bottom right | |
numSlots=4 --number of slots | |
end | |
function s2.draw() | |
background(151, 190, 215, 255) | |
--draw all the slots | |
for i=1,numSlots do | |
s2.DrawSlot(i) | |
end | |
end | |
--this function draws one slot | |
function s2.DrawSlot(i) | |
size=50 | |
pushStyle() | |
fill(78, 125, 148, 255) | |
ellipse(slotsX[i],slotsY[i],size) | |
strokeWidth(1) | |
stroke(66, 109, 141, 255) | |
fill(143, 182, 198, 255) | |
ellipse(slotsX[i]-2,slotsY[i]+2,size) | |
popStyle() | |
end | |
--# Slots3 | |
--Slots3 | |
--draw our ball | |
function s3.setup() | |
size=50 | |
s3.SetupSlots() | |
s3.setupBall() | |
print("add a ball") | |
end | |
function s3.SetupSlots() | |
--set up one in each corner of the screen | |
slotsX={} --x pos | |
slotsY={} --y pos | |
offset=200 | |
slotsX[1]=offset slotsY[1]=HEIGHT-offset --top left | |
slotsX[2]=WIDTH-offset slotsY[2]=HEIGHT-offset --top right | |
slotsX[3]=offset slotsY[3]=offset --bottom left | |
slotsX[4]=WIDTH-offset slotsY[4]=offset --bottom right | |
numSlots=4 --number of slots | |
end | |
--choose a random starting point | |
function s3.setupBall() | |
ballX=WIDTH/2 + 200*(math.random()-.5) | |
ballY=HEIGHT/2 + 200*(math.random()-.5) | |
end | |
function s3.draw() | |
background(151, 190, 215, 255) | |
for i=1,numSlots do | |
s3.DrawSlot(i) | |
end | |
s3.DrawBall() | |
end | |
function s3.DrawSlot(i) | |
pushStyle() | |
fill(78, 125, 148, 255) | |
ellipse(slotsX[i]+2,slotsY[i]-2,size) | |
strokeWidth(1) | |
stroke(66, 109, 141, 255) | |
fill(143, 182, 198, 255) | |
ellipse(slotsX[i],slotsY[i],size) | |
popStyle() | |
end | |
--draw the ball with a shadow too | |
function s3.DrawBall() | |
pushStyle() | |
fill(104, 126, 126, 255) | |
ellipse(ballX+2,ballY-2,size*.9) | |
fill(211, 120, 127, 100) | |
ellipse(ballX,ballY,size*.9) | |
popStyle() | |
end | |
--# Slots4 | |
--Slots4 | |
--get our ball to move as the iPad tilts | |
function s4.setup() | |
size=50 | |
s4.SetupSlots() | |
s4.setupBall() | |
--fix the iPad orientation so the display doesnt rotate as you turn it | |
supportedOrientations(LANDSCAPE_RIGHT) | |
print("move the ball as the iPad tilts") | |
end | |
function s4.SetupSlots() | |
--set up one in each corner of the screen | |
slotsX={} --x pos | |
slotsY={} --y pos | |
offset=200 | |
slotsX[1]=offset slotsY[1]=HEIGHT-offset --top left | |
slotsX[2]=WIDTH-offset slotsY[2]=HEIGHT-offset --top right | |
slotsX[3]=offset slotsY[3]=offset --bottom left | |
slotsX[4]=WIDTH-offset slotsY[4]=offset --bottom right | |
numSlots=4 --number of slots | |
end | |
function s4.setupBall() | |
ballX=WIDTH/2 + 200*(math.random()-.5) | |
ballY=HEIGHT/2 + 200*(math.random()-.5) | |
ballSize=size*.9 | |
ballSpeed=2 | |
end | |
function s4.draw() | |
background(151, 190, 215, 255) | |
for i=1,numSlots do | |
s4.DrawSlot(i) | |
end | |
s4.DrawBall() | |
end | |
function s4.DrawSlot(i) | |
pushStyle() | |
fill(78, 125, 148, 255) | |
ellipse(slotsX[i]+2,slotsY[i]-2,size) | |
strokeWidth(1) | |
stroke(66, 109, 141, 255) | |
fill(143, 182, 198, 255) | |
ellipse(slotsX[i],slotsY[i],size) | |
popStyle() | |
end | |
function s4.DrawBall() | |
--adjust position -- this is the new code | |
--it is simpler than it looks | |
--it takes the current x (or y) position, adds "gravity" (depending on the tilt of the iPad) | |
--with a minimum value of 0 and a maximum of width/height, ie the ball can't go past the edge | |
ballX=math.max(ballSize/2,math.min(WIDTH-ballSize/2,ballX+Gravity.x*ballSpeed)) | |
ballY=math.max(ballSize/2,math.min(HEIGHT-ballSize/2,ballY+Gravity.y*ballSpeed)) | |
--draw ball as usual | |
pushStyle() | |
fill(104, 126, 126, 255) | |
ellipse(ballX+2,ballY-2,ballSize) | |
fill(211, 120, 127, 100) | |
ellipse(ballX,ballY,ballSize) | |
popStyle() | |
end | |
--# Slots5 | |
--Slots5 | |
--get our ball to fall into a slot if it gets close enough | |
function s5.setup() | |
size=50 | |
s5.SetupSlots() | |
s5.setupBall() | |
supportedOrientations(LANDSCAPE_RIGHT) | |
print("get our ball to fall into slots") | |
end | |
function s5.SetupSlots() | |
--set up one in each corner of the screen | |
slotsX={} --x pos | |
slotsY={} --y pos | |
offset=200 | |
slotsX[1]=offset slotsY[1]=HEIGHT-offset --top left | |
slotsX[2]=WIDTH-offset slotsY[2]=HEIGHT-offset --top right | |
slotsX[3]=offset slotsY[3]=offset --bottom left | |
slotsX[4]=WIDTH-offset slotsY[4]=offset --bottom right | |
numSlots=4 --number of slots | |
end | |
function s5.setupBall() | |
ballX=WIDTH/2 + 200*(math.random()-.5) | |
ballY=HEIGHT/2 + 200*(math.random()-.5) | |
ballSize=size*.9 | |
ballSpeed=2 | |
ballMove=true --NEW this will be set to false when the ball lands in a slot | |
end | |
function s5.draw() | |
background(151, 190, 215, 255) | |
for i=1,numSlots do | |
s5.DrawSlot(i) | |
end | |
s5.DrawBall() | |
end | |
function s5.DrawSlot(i) | |
pushStyle() | |
fill(78, 125, 148, 255) | |
ellipse(slotsX[i]+2,slotsY[i]-2,size) | |
strokeWidth(1) | |
stroke(66, 109, 141, 255) | |
fill(143, 182, 198, 255) | |
ellipse(slotsX[i],slotsY[i],size) | |
popStyle() | |
end | |
function s5.DrawBall() | |
--adjust position | |
if ballMove then --if we're not in a slot, then move using gravity | |
ballX=math.max(ballSize/2,math.min(WIDTH-ballSize/2,ballX+Gravity.x*ballSpeed)) | |
ballY=math.max(ballSize/2,math.min(HEIGHT-ballSize/2,ballY+Gravity.y*ballSpeed)) | |
--test if we've fallen into any slots | |
for i=1,numSlots do | |
--fall into slot if we are within half the combined radius of ball and slot | |
if vec2(ballX,ballY):dist(vec2(slotsX[i],slotsY[i]))<(size+ballSize)/4 then | |
--if we fall into a slot, set the x and y position to the centre of the slot | |
--and set ballMove to false | |
ballX=slotsX[i] | |
ballY=slotsY[i] | |
ballMove=false | |
end | |
end | |
end | |
pushStyle() | |
fill(104, 126, 126, 255) | |
ellipse(ballX+2,ballY-2,ballSize) | |
fill(211, 120, 127, 100) | |
ellipse(ballX,ballY,ballSize) | |
popStyle() | |
end | |
--# Slot6 | |
--Slots6 | |
--test the use of gravity | |
--why? We need more balls, and it is difficult to collide them accurately | |
--physics will do it for us | |
--so we set up a little trial to see if we can control a ball using physics and tilting the iPad | |
function s6.setup() | |
s6.CreateBall() | |
s6.CreateWalls() --create walls to bounce off | |
supportedOrientations(LANDSCAPE_RIGHT) | |
print("try using physics to move the ball") | |
end | |
function s6.CreateBall() | |
--create a physics object for our ball | |
--the object is invisible, we draw the ball on top of it | |
--but we can use its x and y position to tell us where to draw | |
ballSize=50 | |
ballX=200 ballY=300 | |
b=physics.body(CIRCLE,ballSize/2) --note we use radius not diameter here | |
b.x=ballX b.y=ballY --initial position of physics body | |
b.restitution=0.6 --bounciness when it hits sides or another ball | |
end | |
--create a wall round each edge so our balls have something to bounce off | |
--there is a special physics object EDGE for this purpose (basically it's a straight line) | |
function s6.CreateWalls() | |
w1=physics.body(EDGE,vec2(0,0),vec2(WIDTH,0)) | |
w2=physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT)) | |
w3=physics.body(EDGE,vec2(0,HEIGHT),vec2(WIDTH,HEIGHT)) | |
w4=physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT)) | |
end | |
function s6.draw() | |
background(151, 190, 215, 255) | |
--tell Codea to use the iPad orientation to set gravity | |
physics.gravity(Gravity) | |
fill(255) | |
--draw the ball over the top of the physics object (ie same x and y) | |
ellipse(b.x,b.y,ballSize) | |
end | |
--# Slot7 | |
--Slots7 | |
--add gravity to our previous work | |
function s7.setup() | |
size=50 | |
s7.CreateWalls() | |
s7.SetupSlots() | |
s7.setupBall() | |
supportedOrientations(LANDSCAPE_RIGHT) | |
print("use physics and tilting to put the ball in a slot") | |
end | |
--create a wall round each edge so our balls have something to bounce off | |
--there is a special physics object EDGE for this purpose (basically it's a straight line) | |
function s7.CreateWalls() | |
w1=physics.body(EDGE,vec2(0,0),vec2(WIDTH,0)) | |
w2=physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT)) | |
w3=physics.body(EDGE,vec2(0,HEIGHT),vec2(WIDTH,HEIGHT)) | |
w4=physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT)) | |
end | |
function s7.SetupSlots() | |
--set up one in each corner of the screen | |
slotsX={} --x pos | |
slotsY={} --y pos | |
offset=200 | |
slotsX[1]=offset slotsY[1]=HEIGHT-offset --top left | |
slotsX[2]=WIDTH-offset slotsY[2]=HEIGHT-offset --top right | |
slotsX[3]=offset slotsY[3]=offset --bottom left | |
slotsX[4]=WIDTH-offset slotsY[4]=offset --bottom right | |
numSlots=4 --number of slots | |
end | |
function s7.setupBall() | |
ballX=WIDTH/2 + 200*(math.random()-.5) | |
ballY=HEIGHT/2 + 200*(math.random()-.5) | |
ballSize=size*.9 | |
ballMove=true --can ball roll | |
b=physics.body(CIRCLE,ballSize/2) --note we use radius not diameter here | |
b.x=ballX b.y=ballY --initial position | |
b.restitution=0.6 --bounciness when it hits sides or another ball | |
end | |
function s7.draw() | |
background(151, 190, 215, 255) | |
--tell Codea to use the iPad orientation to set gravity | |
physics.gravity(Gravity) | |
for i=1,numSlots do | |
s7.DrawSlot(i) | |
end | |
s7.DrawBall() | |
end | |
function s7.DrawSlot(i) | |
pushStyle() | |
fill(78, 125, 148, 255) | |
ellipse(slotsX[i]+2,slotsY[i]-2,size) | |
strokeWidth(1) | |
stroke(66, 109, 141, 255) | |
fill(143, 182, 198, 255) | |
ellipse(slotsX[i],slotsY[i],size) | |
popStyle() | |
end | |
function s7.DrawBall() | |
--test if we've fallen into any holes | |
if ballMove then | |
ballX=b.x | |
ballY=b.y | |
for i=1,numSlots do | |
if vec2(ballX,ballY):dist(vec2(slotsX[i],slotsY[i]))<(size+ballSize)/4 then | |
ballX=slotsX[i] | |
ballY=slotsY[i] | |
ballMove=false | |
end | |
end | |
end | |
pushStyle() | |
fill(104, 126, 126, 255) | |
ellipse(ballX+2,ballY-2,ballSize) | |
fill(211, 120, 127, 100) | |
ellipse(ballX,ballY,ballSize) | |
popStyle() | |
end | |
--get rid of physics object when we're done | |
function s7.Cleanup() | |
b:destroy() | |
end | |
--# Slots8 | |
--Slots8 | |
--add more balls | |
function s8.setup() | |
size=50 | |
s8.CreateWalls() | |
s8.SetupSlots() | |
s8.setupBalls() | |
supportedOrientations(LANDSCAPE_RIGHT) | |
print("add more balls") | |
end | |
--create a wall round each edge so our balls have something to bounce off | |
--there is a special physics object EDGE for this purpose (basically it's a straight line) | |
function s8.CreateWalls() | |
w1=physics.body(EDGE,vec2(0,0),vec2(WIDTH,0)) | |
w2=physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT)) | |
w3=physics.body(EDGE,vec2(0,HEIGHT),vec2(WIDTH,HEIGHT)) | |
w4=physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT)) | |
end | |
function s8.SetupSlots() | |
--set up one in each corner of the screen | |
slotsX={} --x pos | |
slotsY={} --y pos | |
offset=200 | |
slotsX[1]=offset slotsY[1]=HEIGHT-offset --top left | |
slotsX[2]=WIDTH-offset slotsY[2]=HEIGHT-offset --top right | |
slotsX[3]=offset slotsY[3]=offset --bottom left | |
slotsX[4]=WIDTH-offset slotsY[4]=offset --bottom right | |
numSlots=4 --number of slots | |
end | |
function s8.setupBalls() | |
numBalls=4 | |
balls={} | |
for i=1,numBalls do | |
b={} | |
b.x=WIDTH/2 + 200*(math.random()-.5) | |
b.y=HEIGHT/2 + 200*(math.random()-.5) | |
ballSize=size*.9 | |
b.move=true --can ball roll | |
b.p=physics.body(CIRCLE,ballSize/2) --note we use radius not diameter here | |
b.p.x=b.x | |
b.p.y=b.y --initial position | |
b.p.restitution=0.6 --bounciness when it hits sides or another ball | |
table.insert(balls,b) | |
end | |
end | |
function s8.draw() | |
background(151, 190, 215, 255) | |
--tell Codea to use the iPad orientation to set gravity | |
physics.gravity(Gravity) | |
for i=1,numSlots do | |
s8.DrawSlot(i) | |
end | |
for i=1,numBalls do | |
s8.DrawBall(i) | |
end | |
end | |
function s8.DrawSlot(i) | |
pushStyle() | |
fill(78, 125, 148, 255) | |
ellipse(slotsX[i]+2,slotsY[i]-2,size) | |
strokeWidth(1) | |
stroke(66, 109, 141, 255) | |
fill(143, 182, 198, 255) | |
ellipse(slotsX[i],slotsY[i],size) | |
popStyle() | |
end | |
function s8.DrawBall(i) | |
--test if we've fallen into any holes | |
b=balls[i] --just to save us typing and make the code neater | |
if b.move then | |
b.x=b.p.x | |
b.y=b.p.y | |
for i=1,numSlots do | |
if vec2(b.x,b.y):dist(vec2(slotsX[i],slotsY[i]))<(size+ballSize)/4 then | |
b.x=slotsX[i] | |
b.y=slotsY[i] | |
b.move=false | |
end | |
end | |
else | |
b.p.x=b.x | |
b.p.y=b.y | |
end | |
pushStyle() | |
fill(104, 126, 126, 255) | |
ellipse(b.x+2,b.y-2,ballSize) | |
fill(211, 120, 127, 100) | |
ellipse(b.x,b.y,ballSize) | |
popStyle() | |
end | |
--get rid of physics objects when we're done | |
function s8.Cleanup() | |
for i=1,numBalls do | |
balls[i].p:destroy() | |
end | |
balls=nil | |
end | |
--# Slot9 | |
--Slots9 | |
--get our balls to fall out of the slots if we tilt too much | |
function s9.setup() | |
size=50 | |
s9.CreateWalls() | |
s9.SetupSlots() | |
s9.setupBalls() | |
slotThreshold=(size+ballSize)/4 | |
tiltThreshold=0.7 | |
supportedOrientations(LANDSCAPE_RIGHT) | |
print("make the balls fall out of slots if the iPad tilts too much") | |
end | |
--create a wall round each edge so our balls have something to bounce off | |
--there is a special physics object EDGE for this purpose (basically it's a straight line) | |
function s9.CreateWalls() | |
w1=physics.body(EDGE,vec2(0,0),vec2(WIDTH,0)) | |
w2=physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT)) | |
w3=physics.body(EDGE,vec2(0,HEIGHT),vec2(WIDTH,HEIGHT)) | |
w4=physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT)) | |
end | |
function s9.SetupSlots() | |
--set up one in each corner of the screen | |
slotsX={} --x pos | |
slotsY={} --y pos | |
offset=200 | |
slotsX[1]=offset slotsY[1]=HEIGHT-offset --top left | |
slotsX[2]=WIDTH-offset slotsY[2]=HEIGHT-offset --top right | |
slotsX[3]=offset slotsY[3]=offset --bottom left | |
slotsX[4]=WIDTH-offset slotsY[4]=offset --bottom right | |
numSlots=4 --number of slots | |
end | |
function s9.setupBalls() | |
numBalls=4 | |
balls={} | |
for i=1,numBalls do | |
b={} | |
b.x=WIDTH/2 + 200*(math.random()-.5) | |
b.y=HEIGHT/2 + 200*(math.random()-.5) | |
ballSize=size*.9 | |
b.move=true --can ball roll | |
b.p=physics.body(CIRCLE,ballSize/2) --note we use radius not diameter here | |
b.p.x=b.x | |
b.p.y=b.y --initial position | |
b.p.restitution=0.6 --bounciness when it hits sides or another ball | |
table.insert(balls,b) | |
end | |
end | |
function s9.draw() | |
background(151, 190, 215, 255) | |
--tell Codea to use the iPad orientation to set gravity | |
physics.gravity(Gravity) | |
for i=1,numSlots do | |
s9.DrawSlot(i) | |
end | |
for i=1,numBalls do | |
s9.DrawBall(i) | |
end | |
end | |
function s9.DrawSlot(i) | |
pushStyle() | |
fill(78, 125, 148, 255) | |
ellipse(slotsX[i]+2,slotsY[i]-2,size) | |
strokeWidth(1) | |
stroke(66, 109, 141, 255) | |
fill(143, 182, 198, 255) | |
ellipse(slotsX[i],slotsY[i],size) | |
popStyle() | |
end | |
function s9.DrawBall(i) | |
--test if we've fallen into any holes | |
b=balls[i] --just to save us typing and make the code neater | |
if b.move then | |
b.x=b.p.x | |
b.y=b.p.y | |
for i=1,numSlots do | |
if vec2(b.x,b.y):dist(vec2(slotsX[i],slotsY[i]))<slotThreshold then | |
b.x=slotsX[i] | |
b.y=slotsY[i] | |
b.move=false | |
end | |
end | |
elseif math.abs(Gravity.x)>tiltThreshold or math.abs(Gravity.y)>tiltThreshold then | |
b.x=b.x+slotThreshold*Gravity.x/tiltThreshold | |
b.y=b.y+slotThreshold*Gravity.y/tiltThreshold | |
b.p.x=b.x | |
b.p.y=b.y | |
b.move=true | |
else | |
b.p.x=b.x | |
b.p.y=b.y | |
end | |
pushStyle() | |
fill(104, 126, 126, 255) | |
ellipse(b.x+2,b.y-2,ballSize) | |
fill(211, 120, 127, 100) | |
ellipse(b.x,b.y,ballSize) | |
popStyle() | |
end | |
--get rid of physics objects when we're done | |
function s9.Cleanup() | |
for i=1,numBalls do | |
balls[i].p:destroy() | |
end | |
balls=nil | |
end | |
--# Slot10 | |
--Slots10 | |
--add some obstacles | |
function s10.setup() | |
size=50 | |
s10.CreateWallsAndObstacles() | |
s10.SetupSlots() | |
s10.setupBalls() | |
slotThreshold=(size+ballSize)/4 | |
tiltThreshold=0.7 | |
supportedOrientations(LANDSCAPE_RIGHT) | |
end | |
--create a wall round each edge so our balls have something to bounce off | |
--there is a special physics object EDGE for this purpose (basically it's a straight line) | |
function s10.CreateWallsAndObstacles() | |
w1=physics.body(EDGE,vec2(0,0),vec2(WIDTH,0)) | |
w2=physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT)) | |
w3=physics.body(EDGE,vec2(0,HEIGHT),vec2(WIDTH,HEIGHT)) | |
w4=physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT)) | |
--obstacles | |
--create a table to hold their positions so we know where to draw them on the screen | |
O={} | |
O[1]={} | |
O[1].start=vec2(100,HEIGHT/2) | |
O[1].finish=vec2(WIDTH-100,HEIGHT/2) | |
O[1].b=physics.body(EDGE,O[1].start,O[1].finish) | |
O[2]={} | |
O[2].start=vec2(WIDTH/2,100) | |
O[2].finish=vec2(WIDTH/2,HEIGHT-100) | |
O[2].b=physics.body(EDGE,O[2].start,O[2].finish) | |
numObstacles=2 | |
print("add some obstacles") | |
end | |
function s10.SetupSlots() | |
--set up one in each corner of the screen | |
slotsX={} --x pos | |
slotsY={} --y pos | |
offset=200 | |
slotsX[1]=offset slotsY[1]=HEIGHT-offset --top left | |
slotsX[2]=WIDTH-offset slotsY[2]=HEIGHT-offset --top right | |
slotsX[3]=offset slotsY[3]=offset --bottom left | |
slotsX[4]=WIDTH-offset slotsY[4]=offset --bottom right | |
numSlots=4 --number of slots | |
end | |
function s10.setupBalls() | |
numBalls=4 | |
balls={} | |
for i=1,numBalls do | |
b={} | |
b.x=WIDTH/2 + 200*(math.random()-.5) | |
b.y=HEIGHT/2 + 200*(math.random()-.5) | |
ballSize=size*.9 | |
b.move=true --can ball roll | |
b.p=physics.body(CIRCLE,ballSize/2) --note we use radius not diameter here | |
b.p.x=b.x | |
b.p.y=b.y --initial position | |
b.p.restitution=0.6 --bounciness when it hits sides or another ball | |
table.insert(balls,b) | |
end | |
end | |
function s10.draw() | |
background(151, 190, 215, 255) | |
--tell Codea to use the iPad orientation to set gravity | |
physics.gravity(Gravity) | |
for i=1,numSlots do | |
s10.DrawSlot(i) | |
end | |
for i=1,numBalls do | |
s10.DrawBall(i) | |
end | |
for i=1,numObstacles do | |
s10:drawObstacles() | |
end | |
end | |
function s10.DrawSlot(i) | |
pushStyle() | |
fill(78, 125, 148, 255) | |
ellipse(slotsX[i]+2,slotsY[i]-2,size) | |
strokeWidth(1) | |
stroke(66, 109, 141, 255) | |
fill(143, 182, 198, 255) | |
ellipse(slotsX[i],slotsY[i],size) | |
popStyle() | |
end | |
function s10.DrawBall(i) | |
--test if we've fallen into any holes | |
b=balls[i] --just to save us typing and make the code neater | |
if b.move then | |
b.x=b.p.x | |
b.y=b.p.y | |
for i=1,numSlots do | |
if vec2(b.x,b.y):dist(vec2(slotsX[i],slotsY[i]))<slotThreshold then | |
b.x=slotsX[i] | |
b.y=slotsY[i] | |
b.move=false | |
end | |
end | |
elseif math.abs(Gravity.x)>tiltThreshold or math.abs(Gravity.y)>tiltThreshold then | |
b.x=b.x+slotThreshold*Gravity.x/tiltThreshold | |
b.y=b.y+slotThreshold*Gravity.y/tiltThreshold | |
b.p.x=b.x | |
b.p.y=b.y | |
b.move=true | |
else | |
b.p.x=b.x | |
b.p.y=b.y | |
end | |
pushStyle() | |
fill(104, 126, 126, 255) | |
ellipse(b.x+2,b.y-2,ballSize) | |
fill(211, 120, 127, 100) | |
ellipse(b.x,b.y,ballSize) | |
popStyle() | |
end | |
function s10:drawObstacles() | |
pushStyle() | |
strokeWidth(3) | |
lineCapMode(ROUND) | |
stroke(77, 61, 197, 255) | |
for i=1,numObstacles do | |
line(O[i].start.x,O[i].start.y,O[i].finish.x,O[i].finish.y) | |
end | |
popStyle() | |
end | |
--get rid of physics objects when we're done | |
function s10.Cleanup() | |
for i=1,numBalls do | |
balls[i].p:destroy() | |
end | |
balls=nil | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment