Skip to content

Instantly share code, notes, and snippets.

@dermotbalson
Last active March 18, 2023 17:48
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dermotbalson/6509753 to your computer and use it in GitHub Desktop.
Save dermotbalson/6509753 to your computer and use it in GitHub Desktop.
Pinball
--# Notes
--this project creates a simple pinball game
--instead of flippers, it uses a spherical controller to bounce the ball
--and the physics engine to manage all the collisions
--To run the final step, you will need all the images in this zipfile
--https://www.dropbox.com/s/uv3t6dawvcsh7d6/Pinball.zip
--You need to unzip them and copy them into the Dropbox folder you have linked to Codea, then
--go into Codea's dropbox library, and press the sync button tp download them
--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 using the controls at the upper left of the screen
--Unfortunately, this project uses the full screen, so, to select another tab, you need to press the
--little arrow icon at top left of the screen, to show the controls. Then you can press the icon again
--to make it full screen again
--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
--# Main
--Main
--This code manages which Code tab is run
--it remembers your last choice, and if you select a different one, it runs that instead
local tabs = {}
local fnames = {"setup","draw","touched","collide","orientationChanged","close","restart","keyboard","cleanup"}
local fns = {}
local tabDesc={}
function setup()
for k,v in ipairs(fnames) do --store addresses of key event functions
fns[v] = _G[v]
end
LastCode=readProjectData("Code") or 1 --load stored tab number
parameter.integer("Choose_a_tab",1,#tabs,LastCode,ShowList) --tab selector
parameter.action("Run selected tab", RunCode)
RunCode()
end
function ShowList()
output.clear()
for i=1,#tabs do
print(i,tabDesc[i])
end
end
--these two functions do all the tab switching magic (thanks to Andrew_Stacey)
function localise(n,d)
if d then tabDesc[n]=d end
local t= {}
setmetatable(t,{__index = _G})
--setfenv(2,t)
tabs[n] = t
return t
end
--change tabs
function RunCode()
output.clear()
saveProjectData("Code",Choose_a_tab)
cleanup()
local t = tabs[Choose_a_tab]
for k,v in ipairs(fnames) do
if t[v] then _G[v] = t[v] else _G[v] = fns[v] end -- overwrite with the new code
end
setup()
end
--default empty function to avoid errors for tabs that don't have it
function cleanup()
end
--# Step_1
if localise then _ENV=localise(1,"Build controller") end --you can DELETE this if you copy this code to another project
--we'll start with the controller
--from the beginning, we'll force the iPad to be held long side up
--we'll also use the full screen
--(how do you select a code tab to use if you can't see the tab selector?)
--(Answer-press the little left arrow at top of screen while the program runs)
--(this toggles full screen on and off)
--I was going to only show the top half of the ball controller, but it is quite small
--and difficult to reach, so I'm showing the whole ball
--I can still create the illusion of a semi circle by drawing a solid block of colour along the bottom
--I'd like to try varying the shape of the controller, maybe squashing it, but I need to put a physics
--object behind it to handle bouncing, and physics can only do circular objects, so circular it will be
--I've also drawn the ball we'll bounce around the screen
displayMode(FULLSCREEN)
supportedOrientations(PORTRAIT)
function setup()
controlColour=color(217, 181, 58, 255)
controlSize=150
blockColour=color(121, 112, 40, 255)
blockHeight=50
ballColour=color(172, 172, 165, 255)
ballSize=40
end
function draw()
background(0) --black background for now
--ball controller
pushStyle()
fill(controlColour)
ellipse(WIDTH/2,blockHeight,controlSize)
--colour block along bottom
fill(blockColour)
rect(0,0,WIDTH,blockHeight)
--ball
fill(ballColour)
ellipse(WIDTH/2,300,ballSize)
popStyle()
end
--# Step_2
if localise then _ENV = localise(2,"Split code into functions") end --you can DELETE this if you copy this code to another project
--Having designed my controller, I move all the code into functions to keep it separate and clean
--This also makes it easy for you to change them, if you prefer a different colour or shape
--it's very important to compartmentalise code once you have it working
--it makes it much easier to debug problems, than if you just have one big mess of code
displayMode(FULLSCREEN)
supportedOrientations(PORTRAIT)
function setup()
setupScreen()
end
function setupScreen()
controlColour=color(217, 181, 58, 255)
controlSize=150
controlX=WIDTH/2 --initial position
blockColour=color(121, 112, 40, 255)
blockHeight=50
ballColour=color(172, 172, 165, 255)
ballSize=40
ballPos=vec2(WIDTH/2,300)
end
function draw()
background(0)
drawTable()
end
--this function will draw all the objects on the table
function drawTable()
pushStyle()
--ball controller
fill(controlColour)
ellipse(controlX,blockHeight,controlSize)
--colour block along bottom
fill(blockColour)
rect(0,0,WIDTH,blockHeight)
--ball
fill(ballColour)
ellipse(ballPos.x,ballPos.y,ballSize)
popStyle()
end
--# Step_3
if localise then _ENV = localise(3,"Add physics objects") end --you can DELETE this if you copy this code to another project
--now we'll add the basic physics objects
--walls around three sides, but not the bottom
--one for the ball controller too
--and one for the ball that will bounce around
--there is one tricky problem caused by all the different tabs in this project
--if you choose a different tab, we need to carefully remove all the physics objects from the current tab first
--otherwise they will live on and cause problems
--the easiest way to do this is to keep a list of them in a table, so we can just loop theough the table
--and delete them. So that's what the table called bodies is for.
displayMode(FULLSCREEN)
supportedOrientations(PORTRAIT)
function setup()
setupScreen()
end
function setupScreen()
bodies={} --table to hold physics bodies
controlColour=color(217, 181, 58, 255)
controlSize=150
controlX=WIDTH/2
blockColour=color(121, 112, 40, 255)
blockHeight=50
ballColour=color(172, 172, 165, 255)
ballSize=40
ballPos=vec2(WIDTH/2,300)
--physics bodies
controlBody=physics.body(CIRCLE,controlSize/2)
controlBody.type=STATIC --prevents controller moving when ball hits it
--(or from falling through floor due to gravity)
controlBody.x=controlX --starting position
controlBody.y=blockHeight
controlBody.linearVelocity=vec2(0,0) --prevent it moving when ball hits it
controlBody.restitution=3 --bounciness
table.insert(bodies,controlBody)
ballBody=physics.body(CIRCLE,ballSize/2)
ballBody.x=ballPos.x --starting position
ballBody.y=ballPos.y
ballBody.restitution=.8 --bounciness
ballBody.gravityScale=0.2 --gravity as fraction of normal
--(table is tilted but not vertical, so gravity is reduced)
table.insert(bodies,ballBody)
walls={} --we'll keep the walls in a little table
walls[1]=physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT)) --left
walls[2]=physics.body(EDGE,vec2(0,HEIGHT),vec2(WIDTH,HEIGHT)) --top
walls[3]=physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT)) --right
for i=1,3 do
walls[i].restitution=0.9 --bounciness
table.insert(bodies,walls[i]) --put bodies in our list
end
end
function draw()
background(0)
drawTable()
end
function drawTable()
pushStyle()
--ball controller
fill(controlColour)
--note now we use the physics object position
--it's important to do this so if something goes wrong, you can at least see where the physics object is
ellipse(controlBody.x,controlBody.y,controlSize)
--ball
fill(ballColour)
ellipse(ballBody.x,ballBody.y,ballSize) --note now we use the physics object position
popStyle()
--colour block along bottom
fill(blockColour)
rect(0,0,WIDTH,blockHeight)
end
--destroy physics bodies before going to run a different tab
function cleanup()
for i,b in pairs(bodies) do
b:destroy()
end
bodies=nil
controlBody:destroy()
controlBody=nil
ballBody:destroy()
ballBody=nil
for i=1,#walls do
walls[i]:destroy()
end
walls=nil
end
--# Step_4
if localise then _ENV = localise(4,"Make controller work") end --you can DELETE this if you copy this code to another project
--now let's move the controller and try to keep the ball in play
--we need to include a touched function, see near bottom
displayMode(FULLSCREEN)
supportedOrientations(PORTRAIT)
function setup()
setupScreen()
end
function setupScreen()
bodies={} --table to hold physics bodies
controlColour=color(217, 181, 58, 255)
controlSize=150
controlX=WIDTH/2
blockColour=color(121, 112, 40, 255)
blockHeight=50
ballColour=color(172, 172, 165, 255)
ballSize=40
ballPos=vec2(WIDTH/2,300)
--physics bodies
controlBody=physics.body(CIRCLE,controlSize/2)
controlBody.type=STATIC --prevents controller moving when ball hits it
--(or from falling through floor due to gravity)
controlBody.x=controlX --starting position
controlBody.y=blockHeight
controlBody.linearVelocity=vec2(0,0) --prevent it moving when ball hits it
controlBody.restitution=1.3 --bounciness --PLAY WITH DIFFERENT VALUES FOR THIS (if >1, speeds up ball)
table.insert(bodies,controlBody)
ballBody=physics.body(CIRCLE,ballSize/2)
ballBody.x=ballPos.x --starting position
ballBody.y=ballPos.y
ballBody.restitution=.8 --bounciness
ballBody.gravityScale=0.5 --gravity as fraction of normal
--(table is tilted but not vertical, so gravity is reduced)
table.insert(bodies,ballBody)
walls={} --we'll keep the walls in a little table
walls[1]=physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT)) --left
walls[2]=physics.body(EDGE,vec2(0,HEIGHT),vec2(WIDTH,HEIGHT)) --top
walls[3]=physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT)) --right
for i=1,3 do
walls[i].restitution=0.9 --bounciness
table.insert(bodies,walls[i]) --put bodies in our list
end
end
function draw()
background(0)
drawTable()
end
function drawTable()
pushStyle()
--ball controller
fill(controlColour)
--note now we use the physics object position
--it's important to do this so if something goes wrong, you can at least see where the physics object is
ellipse(controlBody.x,controlBody.y,controlSize)
--ball
fill(ballColour)
ellipse(ballBody.x,ballBody.y,ballSize) --note now we use the physics object position
popStyle()
--colour block along bottom
fill(blockColour)
rect(0,0,WIDTH,blockHeight)
end
--trap touches on the controller
function touched(touch)
--this is a slider control so we are only interested in sliding movements
--the touch.state has three values that tells us about the touch
--BEGAN = touch just started
--MOVING = touch still in progress <-- this is the one we want
--ENDED = touch has ended
if touch.state==MOVING then
--we want to trap touches on the visible controller, which is a semi circle
--the easiest way is to test if
--(a) the touch is above the controller centre, and
--(b) the touch is within controlSize/2 of the controller centre
if touch.y>blockHeight and vec2(touch.x,touch.y):dist(vec2(controlBody.x,controlBody.y))<controlSize/2 then
controlBody.x=touch.x --that's all we need!
end
end
end
--destroy physics bodies before going to run a different tab
function cleanup()
for i,b in pairs(bodies) do
b:destroy()
end
bodies=nil
controlBody:destroy()
controlBody=nil
ballBody:destroy()
ballBody=nil
for i=1,#walls do
walls[i]:destroy()
end
walls=nil
end
--# Step_5
if localise then _ENV = localise(5,"Add 3 planets") end --you can DELETE this if you copy this code to another project
--now we can add some more stuff on the screen
--I'm going to use a space theme with planets - this is convenient because they are circular, which is easiest
--I'll add three planets to start with
displayMode(FULLSCREEN)
supportedOrientations(PORTRAIT)
function setup()
setupScreen()
end
function setupScreen()
bodies={} --table to hold physics bodies
--controller
controlColour=color(217, 181, 58, 255)
controlSize=150
controlX=WIDTH/2
blockColour=color(121, 112, 40, 255)
blockHeight=50
--ball
ballColour=color(172, 172, 165, 255)
ballSize=40
ballPos=vec2(WIDTH/2,300)
--objects - there are going to be quite a few, so let's put them in a table
--within this table, each planet will have its own table with various properties
objects={}
objects[1]={colour=color(169, 126, 78, 255),size=20,x=150,y=300,points=100} --Mercury
objects[2]={colour=color(178, 168, 108, 255),size=50,x=250,y=400,points=60} --Venus
objects[3]={colour=color(105, 219, 217, 255),size=50,x=350,y=500,points=60} --Earth
--physics bodies
controlBody=physics.body(CIRCLE,controlSize/2)
controlBody.type=STATIC
controlBody.x=controlX
controlBody.y=blockHeight
controlBody.linearVelocity=vec2(0,0)
controlBody.restitution=1.3
table.insert(bodies,controlBody)
ballBody=physics.body(CIRCLE,ballSize/2)
ballBody.x=ballPos.x
ballBody.y=ballPos.y
ballBody.restitution=.8
ballBody.gravityScale=0.5 --gravity as fraction of normal
table.insert(bodies,ballBody)
--now you'll see one good reason for putting all our planets in a table
--one loop creates all their physics bodies
for i=1,#objects do
b=physics.body(CIRCLE,objects[i].size/2) -- size=diam, but we need radius
b.x=objects[i].x
b.y=objects[i].y
b.type=STATIC --planets don't move
b.info=i --identifier, so when we hit them, we can tell which one it was
objects[i].body=b --so we can keep track of them
table.insert(bodies,b) --for cleanup at the end
end
walls={} --we'll keep the walls in a little table
walls[1]=physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT)) --left
walls[2]=physics.body(EDGE,vec2(0,HEIGHT),vec2(WIDTH,HEIGHT)) --top
walls[3]=physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT)) --right
for i=1,3 do
walls[i].restitution=0.9
table.insert(bodies,walls[i])
end
end
function draw()
background(0)
drawTable()
end
function drawTable()
pushStyle()
--objects first
for i=1,#objects do
fill(objects[i].colour)
ellipse(objects[i].x,objects[i].y,objects[i].size)
end
--ball controller
fill(controlColour)
ellipse(controlBody.x,controlBody.y,controlSize)
--ball
fill(ballColour)
ellipse(ballBody.x,ballBody.y,ballSize) --note now we use the physics object position
popStyle()
--colour block along bottom
fill(blockColour)
rect(0,0,WIDTH,blockHeight)
end
--trap touches on the controller
function touched(touch)
if touch.state==MOVING then
if touch.y>blockHeight and vec2(touch.x,touch.y):dist(vec2(controlBody.x,controlBody.y))<controlSize/2 then
controlBody.x=touch.x --that's all we need!
end
end
end
--destroy physics bodies before going to run a different tab
function cleanup()
for i,b in pairs(bodies) do
b:destroy()
end
bodies=nil
controlBody:destroy()
controlBody=nil
ballBody:destroy()
ballBody=nil
for i=1,#walls do
walls[i]:destroy()
end
walls=nil
end
--# Step_6
if localise then _ENV = localise(6,"Add more planets, get them moving") end --you can DELETE this if you copy this code to another project
--I'm going to add all the planets
--I'm getting a bit ambitious now, but I'd like to try getting the planets moving in a kind of orbit
--I'll start by just getting them to move from left to right repeatedly
displayMode(FULLSCREEN)
supportedOrientations(PORTRAIT)
function setup()
setupScreen()
end
function setupScreen()
bodies={} --table to hold physics bodies
--controller
controlColour=color(217, 181, 58, 255)
controlSize=150
controlX=WIDTH/2
blockColour=color(121, 112, 40, 255)
blockHeight=50
--ball
ballColour=color(232, 46, 206, 255) --CHANGED THIS TO STAND OUT MORE
ballSize=40
ballPos=vec2(WIDTH/2,300)
--objects - there are going to be quite a few, so let's put them in a table
--within this table, each planet will have its own table with various properties
--I'll include an x value but not set it yet, we'll do that underneath
--I'll define the y value as a proportion of screen height, and multiply by HEIGHT underneath
--this means it will work on different size screens, better than defining specific pixel positions
objects={}
objects[1]={colour=color(169, 126, 78, 255),size=20,x=0,y=.2,points=100,speed=200} --Mercury
objects[2]={colour=color(178, 168, 108, 255),size=50,x=0,y=.25,points=60,speed=140} --Venus
objects[3]={colour=color(105, 219, 217, 255),size=50,x=0,y=.33,points=60,speed=120} --Earth
objects[4]={colour=color(220, 89, 41, 255),size=40,x=0,y=.4,points=70,speed=100} --Mars
objects[5]={colour=color(218, 146, 105, 255),size=125,x=0,y=.55,points=30,speed=70} --Jupiter
objects[6]={colour=color(218, 215, 105, 255),size=90,x=0,y=.7,points=60,speed=50} --Saturn
objects[7]={colour=color(116, 145, 188, 255),size=70,x=0,y=.8,points=70,speed=30} --Uranus
objects[8]={colour=color(46, 58, 167, 255),size=70,x=0,y=.9,points=80,speed=20} --Neptune
--set the x value randomly
for i=1,#objects do
objects[i].x=math.random(objects[i].size,WIDTH-objects[i].size)
objects[i].y=objects[i].y*HEIGHT
--randomly reverse direction of movement (make planet move left, with 50% probability)
if math.random()<.5 then
objects[i].speed=-objects[i].speed
end
end
--physics bodies
controlBody=physics.body(CIRCLE,controlSize/2)
controlBody.type=STATIC
controlBody.x=controlX
controlBody.y=blockHeight
controlBody.linearVelocity=vec2(0,0)
controlBody.restitution=1.7 --INCEASED THIS because it is difficult to get past inner planets
table.insert(bodies,controlBody)
ballBody=physics.body(CIRCLE,ballSize/2)
ballBody.x=ballPos.x
ballBody.y=ballPos.y
ballBody.restitution=.8
ballBody.gravityScale=0.5 --gravity as fraction of normal
table.insert(bodies,ballBody)
for i=1,#objects do
b=physics.body(CIRCLE,objects[i].size/2) -- size=diam, but we need radius
b.x=objects[i].x
b.y=objects[i].y
b.type=STATIC --planets don't move
b.info=i --identifier, so when we hit them, we can tell which one it was
objects[i].body=b --so we can keep track of them
table.insert(bodies,b) --for cleanup at the end
end
walls={} --we'll keep the walls in a little table
walls[1]=physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT)) --left
walls[2]=physics.body(EDGE,vec2(0,HEIGHT),vec2(WIDTH,HEIGHT)) --top
walls[3]=physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT)) --right
for i=1,3 do
walls[i].restitution=0.9
table.insert(bodies,walls[i])
end
end
function draw()
background(0)
drawTable()
end
function drawTable()
pushStyle()
--objects first
for i=1,#objects do
--move them, reverse direction if they get to the edge
objects[i].x=objects[i].x+objects[i].speed/60
if objects[i].x<objects[i].size/2 then
objects[i].speed=-objects[i].speed
elseif objects[i].x>WIDTH-objects[i].size/2 then
objects[i].speed=-objects[i].speed
end
--adjust position of physics objects to match
objects[i].body.x=objects[i].x
--draw object
fill(objects[i].colour)
ellipse(objects[i].x,objects[i].y,objects[i].size)
end
--ball controller
fill(controlColour)
ellipse(controlBody.x,controlBody.y,controlSize)
--ball
fill(ballColour)
ellipse(ballBody.x,ballBody.y,ballSize) --note now we use the physics object position
popStyle()
--colour block along bottom
fill(blockColour)
rect(0,0,WIDTH,blockHeight)
end
--trap touches on the controller
function touched(touch)
if touch.state==MOVING then
if touch.y>blockHeight and vec2(touch.x,touch.y):dist(vec2(controlBody.x,controlBody.y))<controlSize/2 then
controlBody.x=touch.x --that's all we need!
end
end
end
function cleanup()
for i,b in pairs(bodies) do
b:destroy()
end
bodies=nil
controlBody:destroy()
controlBody=nil
ballBody:destroy()
ballBody=nil
for i=1,#walls do
walls[i]:destroy()
end
walls=nil
end
--# Step_7
if localise then _ENV = localise(7,"Scoring") end --you can DELETE this if you copy this code to another project
--Now the scoring
--I changed one planet, made Mars score negative, just to add some spice
--to score, we need to identify when a collision occurs, and get the right score
--see the collide function at bottom (this is provided by Codea to help us)
displayMode(FULLSCREEN)
supportedOrientations(PORTRAIT)
function setup()
setupScreen()
score=0 --NEW we can start scoring, now
end
function setupScreen()
bodies={} --table to hold physics bodies
--controller
controlColour=color(217, 181, 58, 255)
controlSize=150
controlX=WIDTH/2
blockColour=color(121, 112, 40, 255)
blockHeight=50
--ball
ballColour=color(232, 46, 206, 255) --CHANGED THIS TO STAND OUT MORE
ballSize=40
ballPos=vec2(WIDTH/2,300)
objects={}
objects[1]={colour=color(169, 126, 78, 255),size=20,x=0,y=.2,points=100,speed=200} --Mercury
objects[2]={colour=color(178, 168, 108, 255),size=50,x=0,y=.25,points=60,speed=140} --Venus
objects[3]={colour=color(105, 219, 217, 255),size=50,x=0,y=.33,points=60,speed=120} --Earth
objects[4]={colour=color(220, 89, 41, 255),size=40,x=0,y=.4,points=-100,speed=100} --Mars
objects[5]={colour=color(218, 146, 105, 255),size=125,x=0,y=.55,points=30,speed=70} --Jupiter
objects[6]={colour=color(218, 215, 105, 255),size=90,x=0,y=.7,points=60,speed=50} --Saturn
objects[7]={colour=color(116, 145, 188, 255),size=70,x=0,y=.8,points=70,speed=30} --Uranus
objects[8]={colour=color(46, 58, 167, 255),size=70,x=0,y=.9,points=80,speed=20} --Neptune
--set the x value randomly
for i=1,#objects do
objects[i].x=math.random(objects[i].size,WIDTH-objects[i].size)
objects[i].y=objects[i].y*HEIGHT
--randomly reverse direction of movement (make planet move left, with 50% probability)
if math.random()<.5 then
objects[i].speed=-objects[i].speed
end
end
--physics bodies
controlBody=physics.body(CIRCLE,controlSize/2)
controlBody.type=STATIC
controlBody.x=controlX
controlBody.y=blockHeight
controlBody.linearVelocity=vec2(0,0)
controlBody.restitution=1.7 --INCEASED THIS because it is difficult to get past inner planets
table.insert(bodies,controlBody)
ballBody=physics.body(CIRCLE,ballSize/2)
ballBody.x=ballPos.x
ballBody.y=ballPos.y
ballBody.restitution=.8
ballBody.gravityScale=0.5 --gravity as fraction of normal
table.insert(bodies,ballBody)
for i=1,#objects do
b=physics.body(CIRCLE,objects[i].size/2) -- size=diam, but we need radius
b.x=objects[i].x
b.y=objects[i].y
b.type=STATIC --planets don't move
b.info=i --identifier, so when we hit them, we can tell which one it was - see collide function at bottom
objects[i].body=b --so we can keep track of them
table.insert(bodies,b) --for cleanup at the end
end
walls={} --we'll keep the walls in a little table
walls[1]=physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT)) --left
walls[2]=physics.body(EDGE,vec2(0,HEIGHT),vec2(WIDTH,HEIGHT)) --top
walls[3]=physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT)) --right
for i=1,3 do
walls[i].restitution=0.9
table.insert(bodies,walls[i])
end
end
function draw()
background(0)
drawTable()
drawStats() --NEW
end
function drawTable()
pushStyle()
--objects first
for i=1,#objects do
--move them, reverse direction if they get to the edge
objects[i].x=objects[i].x+objects[i].speed/60
if objects[i].x<objects[i].size/2 then
objects[i].speed=-objects[i].speed
elseif objects[i].x>WIDTH-objects[i].size/2 then
objects[i].speed=-objects[i].speed
end
--adjust position of physics objects to match
objects[i].body.x=objects[i].x
--draw object
fill(objects[i].colour)
ellipse(objects[i].x,objects[i].y,objects[i].size)
end
--ball controller
fill(controlColour)
ellipse(controlBody.x,controlBody.y,controlSize)
--ball
fill(ballColour)
ellipse(ballBody.x,ballBody.y,ballSize) --note now we use the physics object position
popStyle()
--colour block along bottom
fill(blockColour)
rect(0,0,WIDTH,blockHeight)
end
function drawStats() --NEW for now it will just show the score
pushStyle()
fontSize(24)
font("AmericanTypewriter-Bold")
fill(229, 25, 25, 150)
textMode(CORNER)
text("Score: "..score,70,HEIGHT-50)
popStyle()
end
--trap touches on the controller
function touched(touch)
if touch.state==MOVING then
if touch.y>blockHeight and vec2(touch.x,touch.y):dist(vec2(controlBody.x,controlBody.y))<controlSize/2 then
controlBody.x=touch.x --that's all we need!
end
end
end
--trap collisions
function collide(contact)
--just trap the BEGAN state (when the collision starts)
if contact.state==BEGAN then
--the contact object has information about the two objects colliding stored in bodyA and bodyB
--remember we stored the number of each planet in the info property of its physics object
--so if bodyA is a planet, then bodyA.info will be the number of the planet (same for bodyB)
if contact.bodyA.info~=nil then
score=score+objects[contact.bodyA.info].points
elseif contact.bodyB.info~=nil then
score=score+objects[contact.bodyB.info].points
end
end
end
function cleanup()
for i,b in pairs(bodies) do
b:destroy()
end
bodies=nil
controlBody:destroy()
controlBody=nil
ballBody:destroy()
ballBody=nil
for i=1,#walls do
walls[i]:destroy()
end
walls=nil
end
--# Step_8
if localise then _ENV = localise(8,"Add circular orbits") end --you can DELETE this if you copy this code to another project
--we want the planets follow an orbit around the central controller
--We know the radius of the orbit (distance from the central controller) and speed in pixels per second
--But we need to calculate the position on the circular orbit, at each redraw
--We will need to use the angle to calculate x and y position. If we know the angle A, then
-- x=radius * cos(A)
-- y=radius * sin(A)
--We can calculate how much the angle changes with each redraw, because we know the speed, and we can
--calculate the circumference of the orbit = 2 * pi * radius
--Therefore the change in angle per second = 360 * speed/(2 * pi * radius)
--and we divide by 60 to get the change in angle, per redraw = 360 * speed/(2 * pi * radius) / 60
--Angles are a bit strange in Codea, because rotation is anti-clockwise. So we will need to rotate the angle on
--each side of 90 degrees.
--We can stop a planet going off the screen in two ways. One is to check if the x or y value has left the screen,
--and if it has, we reverse direction. That is quite simple.
--The other way is to calculate the angle at which the planet hits the screen edge, and reverse direction when
--we reach that angle on either side.
--I will use the first method, because it's way simpler.
--Main code changes are marked with ****** below
displayMode(FULLSCREEN)
supportedOrientations(PORTRAIT)
function setup()
setupScreen()
score=0
end
function setupScreen()
bodies={} --table to hold physics bodies
--controller
controlColour=color(217, 181, 58, 255)
controlSize=150
controlX=WIDTH/2
blockColour=color(121, 112, 40, 255)
blockHeight=50
--ball
ballColour=color(232, 46, 206, 255) --CHANGED THIS TO STAND OUT MORE
ballSize=40
ballPos=vec2(WIDTH/2,300)
objects={}
objects[1]={colour=color(169, 126, 78, 255),size=20,x=0,y=.2,points=100,speed=200} --Mercury
objects[2]={colour=color(178, 168, 108, 255),size=50,x=0,y=.25,points=60,speed=140} --Venus
objects[3]={colour=color(105, 219, 217, 255),size=50,x=0,y=.33,points=60,speed=120} --Earth
objects[4]={colour=color(220, 89, 41, 255),size=40,x=0,y=.4,points=-100,speed=100} --Mars
objects[5]={colour=color(218, 146, 105, 255),size=125,x=0,y=.55,points=30,speed=70} --Jupiter
objects[6]={colour=color(218, 215, 105, 255),size=90,x=0,y=.7,points=60,speed=50} --Saturn
objects[7]={colour=color(116, 145, 188, 255),size=70,x=0,y=.8,points=70,speed=30} --Uranus
objects[8]={colour=color(46, 58, 167, 255),size=70,x=0,y=.9,points=80,speed=20} --Neptune
--our orbit calculations
for i=1,#objects do
local P=objects[i] --just to make the code easier to read while we're doing this ******
P.radius=P.y*HEIGHT - blockHeight --radius of orbit ******
local circum=2*math.pi*P.radius --circumference of orbit ******
P.da=P.speed/circum*360/60 --change in angle per redraw ******
if math.random()<.5 then P.da=-P.da end --make it negative half the time, randomly ******
P.a=0 --starting position ******
P.x=controlX --******
P.y=blockHeight+P.radius --******
end
--physics bodies
controlBody=physics.body(CIRCLE,controlSize/2)
controlBody.type=STATIC
controlBody.x=controlX
controlBody.y=blockHeight
controlBody.linearVelocity=vec2(0,0)
controlBody.restitution=1.7 --INCEASED THIS because it is difficult to get past inner planets
table.insert(bodies,controlBody)
ballBody=physics.body(CIRCLE,ballSize/2)
ballBody.x=ballPos.x
ballBody.y=ballPos.y
ballBody.restitution=.8
ballBody.gravityScale=0.5 --gravity as fraction of normal
table.insert(bodies,ballBody)
for i=1,#objects do
b=physics.body(CIRCLE,objects[i].size/2) -- size=diam, but we need radius
b.x=objects[i].x
b.y=objects[i].y
b.type=STATIC --planets don't move
b.info=i --identifier, so when we hit them, we can tell which one it was - see collide function at bottom
objects[i].body=b --so we can keep track of them
table.insert(bodies,b) --for cleanup at the end
end
walls={} --we'll keep the walls in a little table
walls[1]=physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT)) --left
walls[2]=physics.body(EDGE,vec2(0,HEIGHT),vec2(WIDTH,HEIGHT)) --top
walls[3]=physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT)) --right
for i=1,3 do
walls[i].restitution=0.9
table.insert(bodies,walls[i])
end
end
function draw()
background(0)
drawTable()
drawStats() --NEW
end
function drawTable()
pushStyle()
--objects first
for i=1,#objects do
local P=objects[i] --just to make the code easier to read while we're doing this ******
--move them, reverse direction if they get to the edge
P.x=controlX+P.radius*math.sin(math.rad(P.a)) --******
if P.x<P.size/2 or P.x>WIDTH-P.size/2 then P.da=-P.da end --******
P.y=blockHeight+P.radius*math.cos(math.rad(P.a)) --******
if P.y<blockHeight+P.size/2 then P.da=-P.da end --******
--adjust position of physics objects to match
P.body.x=P.x
P.body.y=P.y
P.a=P.a+P.da --adjust angle ******
--draw object
fill(P.colour)
ellipse(P.x,P.y,P.size)
end
--ball controller
fill(controlColour)
ellipse(controlBody.x,controlBody.y,controlSize)
--ball
fill(ballColour)
ellipse(ballBody.x,ballBody.y,ballSize) --note now we use the physics object position
popStyle()
--colour block along bottom
fill(blockColour)
rect(0,0,WIDTH,blockHeight)
end
function drawStats() --NEW for now it will just show the score
pushStyle()
fontSize(24)
font("AmericanTypewriter-Bold")
fill(229, 25, 25, 150)
textMode(CORNER)
text("Score: "..score,70,HEIGHT-50)
popStyle()
end
--trap touches on the controller
function touched(touch)
if touch.state==MOVING then
if touch.y>blockHeight and vec2(touch.x,touch.y):dist(vec2(controlBody.x,controlBody.y))<controlSize/2 then
controlBody.x=touch.x --that's all we need!
end
end
end
--trap collisions
function collide(contact)
--just trap the BEGAN state (when the collision starts)
if contact.state==BEGAN then
--the contact object has information about the two objects colliding stored in bodyA and bodyB
--remember we stored the number of each planet in the info property of its physics object
--so if bodyA is a planet, then bodyA.info will be the number of the planet (same for bodyB)
if contact.bodyA.info~=nil then
score=score+objects[contact.bodyA.info].points
elseif contact.bodyB.info~=nil then
score=score+objects[contact.bodyB.info].points
end
end
end
--destroy physics bodies before going to run a different tab
function cleanup()
for i,b in pairs(bodies) do
b:destroy()
end
bodies=nil
controlBody:destroy()
controlBody=nil
ballBody:destroy()
ballBody=nil
for i=1,#walls do
walls[i]:destroy()
end
walls=nil
end
--# Step_9
if localise then _ENV = localise(9,"Add start/end screens") end --you can DELETE this if you copy this code to another project
--let's give it a proper start screen, and a win and lose screen, and high score
--we need a variable that tells us which "state" we are in
--it can be a good idea to define variables for each state because it makes the code clearer, like so
--here are the state definitions, we are always in one of these states
STARTUP=1 --program has just started, show instructions etc
PLAYING=2
FINISHED=3 --show finished screen, offer to replay
--key changes below are commented and marked with ******
displayMode(FULLSCREEN)
supportedOrientations(PORTRAIT)
function setup()
state=STARTUP --*****
end
function StartGame() ---start playing, set up *******
state=PLAYING
score=0
endMessage=nil
highScore=readLocalData("highScore") or 0 --get high score from where we stored it ******
if bodies~=nil then cleanup() end --destroy everything if we've been playing already
bodies={} --table to hold physics bodies
--controller
controlColour=color(217, 181, 58, 255)
controlSize=150
controlX=WIDTH/2
blockColour=color(121, 112, 40, 255)
blockHeight=50
--ball
ballColour=color(232, 46, 206, 255)
ballSize=40
ballPos=vec2(WIDTH/2,300)
objects={}
objects[1]={colour=color(169, 126, 78, 255),size=20,x=0,y=.2,points=100,speed=200} --Mercury
objects[2]={colour=color(178, 168, 108, 255),size=50,x=0,y=.25,points=60,speed=140} --Venus
objects[3]={colour=color(105, 219, 217, 255),size=50,x=0,y=.33,points=60,speed=120} --Earth
objects[4]={colour=color(220, 89, 41, 255),size=40,x=0,y=.4,points=-100,speed=100} --Mars
objects[5]={colour=color(218, 146, 105, 255),size=125,x=0,y=.55,points=30,speed=70} --Jupiter
objects[6]={colour=color(218, 215, 105, 255),size=90,x=0,y=.7,points=60,speed=50} --Saturn
objects[7]={colour=color(116, 145, 188, 255),size=70,x=0,y=.8,points=70,speed=30} --Uranus
objects[8]={colour=color(46, 58, 167, 255),size=70,x=0,y=.9,points=80,speed=20} --Neptune
--our orbit calculations
for i=1,#objects do
local P=objects[i] --just to make the code easier to read while we're doing this
P.radius=P.y*HEIGHT - blockHeight --radius of orbit
local circum=2*math.pi*P.radius --circumference of orbit
P.da=P.speed/circum*360/60 --change in angle per redraw
if math.random()<.5 then P.da=-P.da end --make it negative half the time, randomly
P.a=0 --starting position
P.x=controlX
P.y=blockHeight+P.radius
end
--physics bodies
controlBody=physics.body(CIRCLE,controlSize/2)
controlBody.type=STATIC
controlBody.x=controlX
controlBody.y=blockHeight
controlBody.linearVelocity=vec2(0,0)
controlBody.restitution=1.7 --INCEASED THIS because it is difficult to get past inner planets
table.insert(bodies,controlBody)
ballBody=physics.body(CIRCLE,ballSize/2)
ballBody.x=ballPos.x
ballBody.y=ballPos.y
ballBody.restitution=.8
ballBody.gravityScale=0.5 --gravity as fraction of normal
table.insert(bodies,ballBody)
for i=1,#objects do
b=physics.body(CIRCLE,objects[i].size/2) -- size=diam, but we need radius
b.x=objects[i].x
b.y=objects[i].y
b.type=STATIC --planets don't move
b.info=i --identifier, so when we hit them, we can tell which one it was - see collide function at bottom
objects[i].body=b --so we can keep track of them
table.insert(bodies,b) --for cleanup at the end
end
walls={} --we'll keep the walls in a little table
walls[1]=physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT)) --left
walls[2]=physics.body(EDGE,vec2(0,HEIGHT),vec2(WIDTH,HEIGHT)) --top
walls[3]=physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT)) --right
for i=1,3 do
walls[i].restitution=0.9
table.insert(bodies,walls[i])
end
end
function draw()
background(0)
if state==STARTUP then --show instructions when starting up *****
showMessage("Move the central controller with your finger\n"..
"to keep the spaceship hitting planets\n(except for Mars, it counts against your score)") -- ********
elseif state==FINISHED then --*******
showMessage(endMessage) --*********
else
drawTable()
drawStats()
end
end
--use consistent messaging style
function showMessage(m) --*******
pushStyle()
fill(255)
font("Copperplate-Bold")
fontSize(48)
text("Cosmic Pinball",WIDTH/2,HEIGHT*.75)
fontSize(24)
font("GillSans-Light")
textWrapWidth(500)
text(m,WIDTH/2,HEIGHT*.65)
sprite("Dropbox:Sun",WIDTH/2,HEIGHT*.4)
text("Touch the screen to start",WIDTH/2,HEIGHT*.2)
popStyle()
end
function drawTable()
pushStyle()
--objects first
for i=1,#objects do
local P=objects[i] --just to make the code easier to read while we're doing this
--move them, reverse direction if they get to the edge
P.x=controlX+P.radius*math.sin(math.rad(P.a))
if P.x<P.size/2 or P.x>WIDTH-P.size/2 then P.da=-P.da end
P.y=blockHeight+P.radius*math.cos(math.rad(P.a))
if P.y<blockHeight+P.size/2 then P.da=-P.da end
--adjust position of physics objects to match
P.body.x=P.x
P.body.y=P.y
P.a=P.a+P.da --adjust angle
--draw object
fill(P.colour)
ellipse(P.x,P.y,P.size)
end
--ball controller
fill(controlColour)
ellipse(controlBody.x,controlBody.y,controlSize)
--ball
fill(ballColour)
ellipse(ballBody.x,ballBody.y,ballSize) --note now we use the physics object position
if ballBody.y<blockHeight then -- END OF GAME! *******
state=FINISHED
if score<500 then endMessage="Better luck next time"
elseif score<1000 then endMessage="Good effort"
elseif score<1500 then endMessage="Excellent!"
else endMessage="Out of this world!" end
endMessage=endMessage.."\n\nScore: "..score
if score>highScore then
saveLocalData("highScore",score) --save high score
endMessage=endMessage.."\n\nHigh score!"
end
end
popStyle()
--colour block along bottom
fill(blockColour)
rect(0,0,WIDTH,blockHeight)
end
function drawStats() --NEW for now it will just show the score
pushStyle()
fontSize(24)
font("AmericanTypewriter-Bold")
fill(229, 25, 25, 150)
textMode(CORNER)
text("Score: "..score,70,HEIGHT-50)
text("High Score: "..highScore,70,HEIGHT-80) ---*****
popStyle()
end
--trap touches on the controller
function touched(touch)
if touch.state==BEGAN and state~=PLAYING then
StartGame()
elseif touch.state==MOVING then
if state==PLAYING then --****** same code in here as before
if touch.y>blockHeight and
vec2(touch.x,touch.y):dist(vec2(controlBody.x,controlBody.y))<controlSize/2 then
controlBody.x=touch.x --that's all we need!
end
end
end
end
--trap collisions
function collide(contact)
--just trap the BEGAN state (when the collision starts)
if contact.state==BEGAN then
--the contact object has information about the two objects colliding stored in bodyA and bodyB
--remember we stored the number of each planet in the info property of its physics object
--so if bodyA is a planet, then bodyA.info will be the number of the planet (same for bodyB)
if contact.bodyA.info~=nil then
score=score+objects[contact.bodyA.info].points
elseif contact.bodyB.info~=nil then
score=score+objects[contact.bodyB.info].points
end
end
end
--destroy physics bodies before going to run a different tab
function cleanup()
for i,b in pairs(bodies) do
b:destroy()
end
bodies=nil
controlBody:destroy()
controlBody=nil
ballBody:destroy()
ballBody=nil
for i=1,#walls do
walls[i]:destroy()
end
walls=nil
end
--# Step10
if localise then _ENV = localise(10,"Use planet images") end --you can DELETE this if you copy this code to another project
--Now we can work on the pretty stuff
--I've imported a picture for each planet, the controller (sun) and the ball (spaceship), plus background
--I also changed the bounciness of each planet - watch out for Mars!
STARTUP=1 --program has just started, show instructions etc
PLAYING=2
FINISHED=3 --show finished screen, offer to replay
displayMode(FULLSCREEN)
supportedOrientations(PORTRAIT)
function setup()
state=STARTUP
end
function StartGame() ---start playing, set up
state=PLAYING
score=0
endMessage=nil
highScore=readLocalData("highScore") or 0 --get high score from where we stored it
if bodies~=nil then cleanup() end --destroy everything if we've been playing already
backImg=readImage("Dropbox:galaxy")
bodies={} --table to hold physics bodies
--controller
controlColour=color(217, 181, 58, 255)
controlSize=150
controlX=WIDTH/2
controlImg=readImage("Dropbox:Sun")
blockColour=color(121, 112, 40, 255)
blockHeight=50
--ball
ballColour=color(232, 46, 206, 255) --CHANGED THIS TO STAND OUT MORE
ballSize=40
ballPos=vec2(WIDTH/2,300)
ballImg=readImage("Space Art:Red Ship")
--r = restitution (bounciness)
objects={}
objects[1]={colour=color(169, 126, 78, 255),size=20,x=0,y=.2,points=100,speed=200,img="Mercury",r=1}
objects[2]={colour=color(178, 168, 108, 255),size=50,x=0,y=.25,points=60,speed=140,img="Venus",r=.9}
objects[3]={colour=color(105, 219, 217, 255),size=50,x=0,y=.33,points=60,speed=120,img="Earth",r=.9}
objects[4]={colour=color(220, 89, 41, 255),size=40,x=0,y=.4,points=-100,speed=100,img="Mars",r=3}
objects[5]={colour=color(218, 146, 105, 255),size=125,x=0,y=.55,points=30,speed=70,img="Jupiter",r=.5}
objects[6]={colour=color(218, 215, 105, 255),size=90,x=0,y=.7,points=100,speed=50,img="Saturn",r=.8}
objects[7]={colour=color(116, 145, 188, 255),size=70,x=0,y=.8,points=150,speed=30,img="Uranus",r=.8}
objects[8]={colour=color(46, 58, 167, 255),size=70,x=0,y=.9,points=200,speed=20,img="Neptune",r=.8}
--our orbit calculations
for i=1,#objects do
local P=objects[i] --just to make the code easier to read while we're doing this
P.radius=P.y*HEIGHT - blockHeight --radius of orbit
local circum=2*math.pi*P.radius --circumference of orbit
P.da=P.speed/circum*360/60 --change in angle per redraw
if math.random()<.5 then P.da=-P.da end --make it negative half the time, randomly
P.a=0 --starting position
P.x=controlX
P.y=blockHeight+P.radius
--get images
objects[i].pic=readImage("Dropbox:"..objects[i].img)
end
--physics bodies
controlBody=physics.body(CIRCLE,controlSize/2)
controlBody.type=STATIC
controlBody.x=controlX
controlBody.y=blockHeight
controlBody.linearVelocity=vec2(0,0)
controlBody.restitution=1.7 --INCEASED THIS because it is difficult to get past inner planets
table.insert(bodies,controlBody)
ballBody=physics.body(CIRCLE,ballSize/2)
ballBody.x=ballPos.x
ballBody.y=ballPos.y
ballBody.restitution=.8
ballBody.gravityScale=0.5 --gravity as fraction of normal
table.insert(bodies,ballBody)
for i=1,#objects do
b=physics.body(CIRCLE,objects[i].size/2) -- size=diam, but we need radius
b.x=objects[i].x
b.y=objects[i].y
b.type=STATIC --planets don't move
b.restitution=objects[i].r
b.info=i --identifier, so when we hit them, we can tell which one it was - see collide function at bottom
objects[i].body=b --so we can keep track of them
table.insert(bodies,b) --for cleanup at the end
end
walls={} --we'll keep the walls in a little table
walls[1]=physics.body(EDGE,vec2(0,0),vec2(0,HEIGHT)) --left
walls[2]=physics.body(EDGE,vec2(0,HEIGHT),vec2(WIDTH,HEIGHT)) --top
walls[3]=physics.body(EDGE,vec2(WIDTH,0),vec2(WIDTH,HEIGHT)) --right
for i=1,3 do
walls[i].restitution=0.9
table.insert(bodies,walls[i])
end
end
function draw()
background(0)
if state==STARTUP then --show instructions when starting up
showMessage("Move the central controller with your finger\n"..
"to keep the spaceship hitting planets\n(except for Mars, it counts against your score)") -- ********
elseif state==FINISHED then
showMessage(endMessage)
else
sprite(backImg,WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)
drawTable()
drawStats()
end
end
--use consistent messaging style
function showMessage(m) --*******
pushStyle()
fill(255)
font("Copperplate-Bold")
fontSize(48)
text("Cosmic Pinball",WIDTH/2,HEIGHT*.75)
fontSize(24)
font("GillSans-Light")
textWrapWidth(500)
text(m,WIDTH/2,HEIGHT*.65)
sprite("Dropbox:Sun",WIDTH/2,HEIGHT*.4)
text("Touch the screen to start",WIDTH/2,HEIGHT*.2)
popStyle()
end
function drawTable()
pushStyle()
--objects first
for i=1,#objects do
local P=objects[i] --just to make the code easier to read while we're doing this
--move them, reverse direction if they get to the edge
P.x=controlX+P.radius*math.sin(math.rad(P.a))
if P.x<P.size/2 or P.x>WIDTH-P.size/2 then P.da=-P.da end
P.y=blockHeight+P.radius*math.cos(math.rad(P.a))
if P.y<blockHeight+P.size/2 then P.da=-P.da end
--adjust position of physics objects to match
P.body.x=P.x
P.body.y=P.y
P.a=P.a+P.da --adjust angle
--draw object
fill(P.colour)
sprite(P.pic,P.x,P.y,P.size)
--ellipse(objects[i].x,objects[i].y,objects[i].size)
end
--ball controller
fill(controlColour)
sprite(controlImg,controlBody.x,controlBody.y,controlSize)
--ellipse(controlBody.x,controlBody.y,controlSize)
--ball
fill(ballColour)
sprite(ballImg,ballBody.x,ballBody.y,ballSize)
--ellipse(ballBody.x,ballBody.y,ballSize) --note now we use the physics object position
if ballBody.y<blockHeight then -- END OF GAME! *******
state=FINISHED
if score<500 then endMessage="Better luck next time"
elseif score<1000 then endMessage="Good effort"
elseif score<1500 then endMessage="Excellent!"
else endMessage="Out of this world!" end
endMessage=endMessage.."\n\nScore: "..score
if score>highScore then
saveLocalData("highScore",score) --save high score
endMessage=endMessage.."\n\nHigh score!"
end
end
popStyle()
--colour block along bottom
fill(blockColour)
rect(0,0,WIDTH,blockHeight)
end
function drawStats() --NEW for now it will just show the score
pushStyle()
fontSize(24)
font("AmericanTypewriter-Bold")
fill(255)
textMode(CORNER)
text("Score: "..score,70,HEIGHT-50)
text("High Score: "..highScore,70,HEIGHT-80)
popStyle()
end
--trap touches on the controller
function touched(touch)
if touch.state==BEGAN and state~=PLAYING then
StartGame()
elseif touch.state==MOVING then
if state==PLAYING then --****** same code in here as before
if touch.y>blockHeight and
vec2(touch.x,touch.y):dist(vec2(controlBody.x,controlBody.y))<controlSize/2 then
controlBody.x=touch.x --that's all we need!
end
end
end
end
--trap collisions
function collide(contact)
--just trap the BEGAN state (when the collision starts)
if contact.state==BEGAN then
--the contact object has information about the two objects colliding stored in bodyA and bodyB
--remember we stored the number of each planet in the info property of its physics object
--so if bodyA is a planet, then bodyA.info will be the number of the planet (same for bodyB)
if contact.bodyA.info~=nil then
score=score+objects[contact.bodyA.info].points
elseif contact.bodyB.info~=nil then
score=score+objects[contact.bodyB.info].points
end
end
end
--destroy physics bodies before going to run a different tab
function cleanup()
for i,b in pairs(bodies) do
b:destroy()
end
bodies=nil
controlBody:destroy()
controlBody=nil
ballBody:destroy()
ballBody=nil
for i=1,#walls do
walls[i]:destroy()
end
walls=nil
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment