Skip to content

Instantly share code, notes, and snippets.

@dermotbalson
Last active August 29, 2015 13:57
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 dermotbalson/9542640 to your computer and use it in GitHub Desktop.
Save dermotbalson/9542640 to your computer and use it in GitHub Desktop.
Dave
--# Main
--Main
--This program contains over 20 mini-projects created by dave1707 to answer questions asked in the forum
--** How to run the projects **
--When you run the program, you can select any of these projects by number using the slider at upper left
--(Underneath the slider you will see a textbox with descriptions of what each numbered project does)
--When you've selected a project, press the button "Run selected project" to run it
--** Viewing the code **
--The code tabs to the right are in the same order as the numbered projects, and each one contains all
--the code you need to run the project.
--** Copying the code to your own project **
--To copy one of the projects to your own separate project, just copy all the code in that tab and paste it
--into your project. You can delete the first line starting "if localise then..." if you want.
--** What is all the code below, in this tab?
--You can ignore the code below. It manages the selection of projects and is quite technical. It has nothing to do with what dave wrote.
--** DON'T TOUCH THE CODE BELOW *****
--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={}
local LastCode,PrevCode,projectList
PN=0
function setup()
for k,v in ipairs(fnames) do --store addresses of key event functions
fns[v] = _G[v]
end
projectList=""
for i=1,#tabs,2 do
if projectList~="" then projectList=projectList.."\n" end
local txt1=GetString(i)
if i<#tabs then
local txt2=tostring(i+1)..": "..tabDesc[i+1]
projectList=projectList..txt1 .. txt2
else
projectList=projectList..txt1
end
end
RunCode()
end
function GetString(i)
pushStyle()
font("SourceSansPro-Regular")
fontSize(12)
local txt=i..": "..tabDesc[i]
local n=textSize(txt)
local s=textSize(" ")/20
popStyle()
local m=(80-n)/s if m<0 then m=1 end
return txt..string.rep(" ",m)
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
end
--change tabs
function RunCode()
if Choose_a_tab then
if LastCode then PrevCode=LastCode end
saveProjectData("DaveTuts",Choose_a_tab)
end
cleanup()
cleanup2()
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
--additional cleanup
function cleanup2()
resetStyle()
collectgarbage()
output.clear()
parameter.clear()
LastCode=readProjectData("DaveTuts") or 1 --load stored tab number
print(string.upper(tabDesc[LastCode]))
parameter.integer("Choose_a_tab",1,#tabs,LastCode) --tab selector
parameter.text("Projects",projectList)
parameter.action("Run selected project", RunCode)
end
--# Snake
--snake example
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"Snake") end
--KNOWLEDGE = basic tables, pairs looping
function setup()
tab={} --define an empty table (array) called tab, to hold the parts of the "snake"
x=WIDTH/2 --set x,y position to centre of screen initially
y=HEIGHT/2
sx=0 --sx and sy will hold the change in direction based on your fi ger movement
sy=0
length=150 --set maximum length of snake
end
--when you touch the screen, figure out the direction
function touched(t)
getDirection()
end
function getDirection()
--CurrentTouch holds the location of the last touch
--calculate distance to the current x,y position
dx=CurrentTouch.x-x
dy=CurrentTouch.y-y
--we will move towards the touch point by 1/25 of the current distance
sx=dx/25
sy=dy/25
end
function draw()
background(40,40,50)
fill(255,0,0)
text("Drag your finger around the screen",WIDTH/2,HEIGHT-50)
--move toward the current touch position
x = x + sx
y = y + sy
--insert a new point at the beginning of our table at x,y
--we store the point as a "vec2", which is just a pair of numbers
table.insert(tab,1,vec2(x,y))
--if our snake is too long, remove the last item to make room
--(#tab gives us the number of items in table tab)
if #tab>length then
table.remove(tab,#tab)
end
--this is a way of looping through all the items in the table
--and drawing a circle at eahc position we have stored
--for each item, we will be given an a and b value
--the a value will be a sequence 1, 2, 3, etc (ie the 5th item will have a=5)
--the b value will be the contents of that item in the table, which is a vec2
--containing an x,y value
for a,b in pairs(tab) do
if a==1 then --the first item gets drawn bigger, as the head
ellipse(b.x,b.y,20,20)
else
ellipse(b.x,b.y,10,10)
end
end
end
--# Touch
-- touch detection
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"Touch") end
--KNOWLEDGE = nil
function setup()
--nothing needed, we could omit the function completely
end
--note all the variables in draw are defined with "local" in front of them
--this is not only faster, but because they aren't needed outside this function
--this means we can safely use the same variable names elsewhere without them
--getting confused with each other
--(We don't have other functions in this example, but I'm trying to set you a good example!)
function draw()
background(40, 40, 50)
fill(255)
text("Slide finger across ellipse or circle",WIDTH/2,HEIGHT-100)
--ellipse
fill(220)
local ex,ey=250,200
local xr,yr=150,100
ellipse(ex,ey,xr*2,yr*2) -- first two items are x,y position, then width, height
--circle
fill(139, 187, 209, 255)
local cx,cy,cr=450,450,100
--a circle uses the ellipse command but only provides width, then height is assumed to be the same
ellipse(cx,cy,cr*2)
--store current touch position
local x=CurrentTouch.x -- touched x value
local y=CurrentTouch.y -- touched y value
-- determine if touched value is inside ellipse
fill(255,0,0)
if (y-ey)^2/xr^2+(x-ex)^2/yr^2 <= 1 then --standard math formula
text("inside",ex,ey)
end
--same for circle
--we could use the same method as above, but because it is a circle, we can try something else
--given two points, Codea can calculate the distance between them for you
--as long as they are in vec2 format, like so
if vec2(cx,cy):dist(vec2(x,y))<cr then --check if dostance is less than radius
text("inside",cx,cy)
end
end
--# Select
--selecting a square
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"Select") end
--KNOWLEDGE = nil
function setup()
size=100 -- size of the squares
squares=5 -- number of squares wide and high
startX,startY=130,100 --bottom left position of table
end
function draw()
background(40,40,50)
fill(255)
text("tap a square",WIDTH/2,HEIGHT-100)
strokeWidth(2) --width of table border
stroke(255)
noFill() --draw empty rectangles
--draw table
for x=1,squares do --loop through from left to right
--the rect command draws a square with the lower left corner at the x,y position we provide
local px=startX+x*size-size --calculate bottom left x value for this square
for y=1,squares do --and loop from bottom to top (remember y=0 at bottom and increases upwards)
local py=startY+y*size-size --calculate y position of the bottom left of the square
rect(px,py,size,size) --draw the square
end
end
if zone then -- square touched, fill with color
fill(255, 0, 0)
local px=startX+tx*size-size --as above
local py=startY+ty*size-size
rect(px,py,size,size) -- draw squares
end
end
function touched(touch)
--touch has three "states" to tell you what is happening
--BEGAN means the touch has just started
--MOVING means the touch is moving across the screen
--ENDED means the touch has just ended
--we could use BEGAN or ENDED for this
if touch.state == ENDED then
--calculate which square was touched, x value first
tx=math.floor((touch.x-startX)/size)+1
--if invalid, exit, set zone to nil
if tx<1 or tx>squares then
zone=nil
return
end
--same for y
ty=math.floor((touch.y-startY)/size)+1
if ty<1 or ty>squares then
zone=nil
return
end
--if we got this far, we have a valid touch, set zone=true
zone=true
end
end
--# Drag
-- drag grid example
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"Drag") end
function setup()
dx=WIDTH/2 --initial centre of grid
dy=HEIGHT/2
end
function draw()
background(40, 40, 50)
pushStyle() --remember current style settings so we can put them back
fontSize(30)
fill(255)
text("Drag grid around",WIDTH/2,HEIGHT-50)
translate(dx,dy) --centre the grid on the current touch position
--draw white circle
fill(255)
ellipse(0,0,100,100)
--set line width, colour
stroke(255)
strokeWidth(4)
--draw the grid, x lines first
for x=-3000,3000,100 do
line(x,-3000,x,3000)
fill(255)
text(x,x,0)
end --y lines
for y=-3000,3000,100 do
line(-3000,y,3000,y)
text(y,0,y)
end
popStyle() --put original style settings back
end
--the "touched" function will tell you when a touch happens
--the parameter t (or whatever else you want to call it) has all the info you need
function touched(t)
--there are 3 situations, you can find out which from the "state" property
--state=BEGAN means the touch just started
--state=MOVING means the user is moving their finger around
--state==ENDED means the user stopped touching
if t.state==BEGAN then --store x,y values when touch starts
x1=t.x
y1=t.y
elseif t.state==MOVING then
dx=dx+t.x-x1 --set dx, dy equal to distance we moved from original start of touch
dy=dy+t.y-y1 --these are used in the draw function to position the grid
x1=t.x
y1=t.y
end
end
--# Drag2
-- faster drag grid example
-- drawing the grid only once, when we start
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"Faster Drag") end
function setup()
dx=WIDTH/2 --initial centre of grid
dy=HEIGHT/2
grid=DrawGrid(6000,6000,100) --draw grid 2000x2000, with square size 100, store in image
end
--function to draw grid
--we put this in its own function to keep things neat
--it also allows us to easily to change the size if we need to
function DrawGrid(w,h,s)
img=image(w,h) --create blank image to hold grid
--we can draw onto this blank image instead of the screen, like this
setContext(img)
pushStyle() --remember current style settings so we can put them back
fontSize(30)
fill(255)
--draw white circle
fill(255)
ellipse(0,0,100,100)
--set line width, colour
stroke(255)
strokeWidth(4)
--draw the grid, x lines first
for x=0,w,s do
line(x,0,x,h)
fill(255)
text(x,x,0)
end --y lines
for y=0,h,s do
line(0,y,w,y)
text(y,0,y)
end
popStyle() --put original style settings back
setContext() --stop drawing on image
return img
end
function draw()
background(40, 40, 50)
text("Drag grid around",WIDTH/2,HEIGHT-50)
sprite(grid,dx,dy) --centre the grid on the current touch position
end
--the "touched" function will tell you when a touch happens
--the parameter t (or whatever else you want to call it) has all the info you need
function touched(t)
--there are 3 situations, you can find out which from the "state" property
--state=BEGAN means the touch just started
--state=MOVING means the user is moving their finger around
--state==ENDED means the user stopped touching
if t.state==BEGAN then --store x,y values when touch starts
x1=t.x
y1=t.y
elseif t.state==MOVING then
dx=dx+t.x-x1 --set dx, dy equal to distance we moved from original start of touch
dy=dy+t.y-y1 --these are used in the draw function to position the grid
x1=t.x
y1=t.y
end
end
--# Button
--button example
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"Button") end
--we don't need to setup anything
function setup()
end
function draw()
background(40, 40, 50)
pushStyle() --remember current style settings so we can put them back
--draw button (see Drag2 tab for how to draw it just once for greater speed)
rectMode(CENTER) --we'll use a rectangle. Set it so it is centred on the position where it is drawn
fill(255) --button colour
rect(150,600,200,100) --draw button
fill(255,0,0) --text colour
text("Change to theme 2",150,620)
fill(0,255,0)
text("Cancel OK",150,580)
popStyle() --put original style settings back
end
--see comments on Touch example for how touch works
function touched(t)
--if touch has just started, check if it is within the button area
if t.state==BEGAN then
if t.x>50 and t.x<150 and t.y>550 and t.y<600 then
print("Cancel pressed")
end
if t.x>150 and t.x<2000 and t.y>550 and t.y<600 then
print("OK pressed")
end
end
end
--# Game
--simple game
--you try to touch buttons which appear randomly and shrink to nothing
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"Game") end
function setup()
--initialise
hit=0
missed=0
createCircle() --create first circle to touch
end
function draw()
background(40, 40, 50)
fontSize(40)
pushStyle() --store style settings
if rad>1 then --if we have a circle (radius>0) then draw it
fill(c)
ellipse(x,y,rad) --draw circle
rad=rad-1 --decrease radius
else --no circle, draw a new one
createCircle()
missed = missed + 1 --we missed, so add to total
end
fill(255)
str=string.format("Hit %d Missed %d",hit,missed)
text(str,WIDTH/2,HEIGHT-50)
text("Try to touch the circle",WIDTH/2,HEIGHT-100)
popStyle() --restore style settings
end
function createCircle()
rad=70+math.random(1,100) --size of circle
x=math.random(25,WIDTH-25)
y=math.random(25,HEIGHT-100)
c=color(math.random(0,255),math.random(0,255),math.random(0,255))
end
function touched(t)
if t.state==BEGAN then
if vec2(x,y):dist(vec2(t.x,t.y))<=rad then
--if (t.y-y)^2/rad^2+(t.x-x)^2/rad^2 <= 1 then -- circle tapped
createCircle()
hit = hit + 1
end
end
end
--# Keyboard
--keyboard example
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"Keyboard") end
function setup()
showKeyboard() --shows on screen keyboard
str="" --initialise text on screen
end
function draw()
background(40,40,50)
fill(255)
text("Enter your name",WIDTH/2,HEIGHT/2+50)
str=keyboardBuffer() --capture typed text
if rtn then --if return was pressed, hide then re-show keyboard
rtn=false
hideKeyboard()
showKeyboard()
end
text(str,WIDTH/2,HEIGHT/2)
end
--this function captures keystrokes
function keyboard(k)
if k==RETURN then --if return pressed, display text
rtn=true --create indicator for the draw function
print(str)
end
end
--# Keyboard2
--keyboard example 2
--this one stores keyboard input in a table so multiple lines can be displayed
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"Keyboard2") end
function setup()
strTab={} --table for typed text
buffer="" --typed keyboard text
showKeyboard()
textMode(CORNER)
end
function draw()
background(30,30,0,255)
fill(255)
text("Keyboard example",100,HEIGHT-100)
text("Type something and press return",100,HEIGHT-150)
--draw text that has already been typed
if buffer~="" then
text(buffer,10,400)
end
--draw previously typed lines of text
for z=1,#strTab do
text(strTab[z],10,420+(#strTab-z)*20)
end
end
function touched()
showKeyboard()
end
function keyboard(key)
if key == RETURN then
--as each line is completed, add it to the table
table.insert(strTab,buffer)
buffer=""
elseif key==BACKSPACE then
buffer=string.sub(buffer,1,string.len(buffer)-1)
else --new key has been pressed, add to current text string
buffer=buffer..key
end
end
--# TextInput
--text input box
--see comments for previous keyboard and touch examples
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"Text input") end
function setup()
hideKeyboard()
showKeyboard()
str=""
nbr=0
end
function draw()
background(40,40,50)
rectMode(CENTER) --set textbox to be centred on the position we give it
fill(255)
if keyboardBuffer() ~= nil then
str=keyboardBuffer()
end
text("number "..nbr,300,730)
text("Enter number then press return",300,640)
rect(300,600,200,50)
fill(255,0,0)
text(str,300,600)
end
function keyboard(k)
if k==RETURN then
hideKeyboard()
nbr=str
if nbr=="" or nbr==nil then
nbr=0
end
end
end
function touched(t)
if t.state==BEGAN then
showKeyboard()
end
end
--# TextInput2
--text input example 2
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"Text input 2") end
function setup()
str = ""
bcolor= 0
x=300
y=500
w=200
h=50
l=x-w/2 --button left
r=x+w/2 --right
b=y-h/2 --bottom
t=y+h/2 --top
end
function draw()
background(30,30,0,255)
strokeWidth(6) --width of border
rectMode(CENTER) --set button and text to be centred
textMode(CENTER)
fill(255)
text("Tap button then input data",x,700)
text("Press RETURN to show input",x,650)
text("Enter value",x,550)
if bcolor == 0 then
fill(255, 0, 0, 255)
else
fill(128,0,0,255)
end
rect(x,y,w,h) -- input area
fill(255)
if keyboardBuffer() ~= nil then
text(keyboardBuffer(),x,500) -- show data as it is keyed
else
text(str,x,500) -- show data in input area
end
text(str,x,450) -- show data below input area
end
--see comments in Touch example
function touched() -- check if input area was touched
if CurrentTouch.x > l and CurrentTouch.x < r then
if CurrentTouch.y > b and CurrentTouch.y < t then
showKeyboard()
bcolor = 1
end
end
end
--see comments in Keyboard example
function keyboard(key) -- move keyboardBuffer to str when return is pressed
if key == RETURN then
str = keyboardBuffer()
hideKeyboard()
bcolor = 0
end
end
--# Timer
--Timer
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"Timer") end
function setup()
et=0 --set elapsed time to 0
end
function draw()
background(40, 40, 50)
fill(255)
timer() --check timer status
--showText is used to tell draw what to do
if showText then
text("show this text until 5 is reached "..math.ceil(et-ElapsedTime),
WIDTH/2,HEIGHT/2)
end
if not showText then
text("tap screen to start timer",WIDTH/2,HEIGHT/2)
end
end
--if the variable s is provided, then we are starting the timer with s seconds
--if it is not provided, we are just checking whether it is time to turn it off
function timer(s)
if s~=nil then --start the timer
et=ElapsedTime+s --ElapsedTime = time since program started
showText=true --used by draw
end
if et-5<ElapsedTime then --if time is up, then disable the timer
showText=false
end
end
--restart the timer with 15 seconds every time the screen is touched
function touched(t)
if t.state==BEGAN then
timer(15)
end
end
--# Restart
-- restart program example
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"Restart") end
--create a couple of physics objects to bounce
function setup()
c1 = physics.body(CIRCLE,50)
c1.x=300
c1.y=900
c2 = physics.body(CIRCLE,50)
c2.x=300
c2.y=200
c2.type=STATIC
end
--restart when they collide
function collide(contact)
if contact.state == BEGAN then
print("\nrestart program")
restart() --this is what we came for!
end
end
function draw()
background(30, 30, 30, 25)
stroke(255)
strokeWidth(1)
noFill()
ellipse(c1.x,c1.y,100,100)
ellipse(c2.x,c2.y,100,100)
end
--# TableFunctions
-- execute functions from a table
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"Table functions") end
--we'll start with three functions a1, a2, a3
function a1()
print("function a1 executed")
end
function a2()
print("function a2 executed")
end
function a3()
print("function a3 executed")
end
--in setup, we'll put them in a table
--we can put functions into a table because the name screen1 doesn't actually hold a function, but
--the address of the function. This address is numeric and can be stored in a table
function setup()
tab={a1,a2,a3}
--now loop through and run each function
for z=1,#tab do
tab[z]() --the function name is in tab[z] and the () tells Codea to run it
end
end
--this isn't needed if you copy this to your own project
--It's needed here, because if we don't have it, Codea may try
--to run one of the draw functions in the other code tabs
function draw()
background(40,40,50)
end
--# State
--Use states to manage what happens (and is drawn)
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"State") end
function setup()
s=1 --initialise state at 1
--there are 3 states, numbered 1 to 3, one for each screen
end
function draw()
fontSize(40)
if s==1 then
screen1()
end
if s==2 then
screen2()
end
if s==3 then
screen3()
end
end
--there is a separate function to draw eahc different screen
--this keeps your code neat
function screen1()
background(255, 220, 0, 94)
fill(255,0,0)
text("screen 1",WIDTH/2,HEIGHT/2)
text("tap screen for next screen",WIDTH/2,HEIGHT/2-200)
end
function screen2()
background(95, 255, 0, 95)
fill(255,0,0)
text("screen 2",WIDTH/2,HEIGHT/2)
text("tap screen for next screen",WIDTH/2,HEIGHT/2-200)
end
function screen3()
background(0, 255, 239, 95)
fill(255,0,0)
text("screen 3",WIDTH/2,HEIGHT/2)
text("tap screen for next screen",WIDTH/2,HEIGHT/2-200)
end
--go to the next screen when the screen is touched
function touched(t)
if t.state==BEGAN then
s=s+1
if s>3 then
s=1
end
end
end
--# State2
--Use NAMED states to manage what happens (and is drawn)
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"State") end
function setup()
s=1 --initialise state at 1
--there are 3 states, numbered 1 to 3, one for each screen
--we'll give them names and their own drawing functions, like so
--naming them makes the later code easier to read and reduces error
states={"Screen1","Screen2","Screen3"} --table of state names
--and a table of functions to draw each of them (see aso TableFunctions example)
--we can put functions into a table because the name screen1 doesn't actually hold a function, but
--the address of the function. This address is numeric and can be stored in a table
stateFunctions={screen1,screen2,screen3}
end
function draw()
fontSize(40)
--run the function for the current state
--the function name is stateFunctions[2]
--we tell Codea to run that function by attaching () on the end
--neat, huh?
stateFunctions[s]()
end
--there is a separate function to draw each different screen
--this keeps your code neat
function screen1()
background(255, 220, 0, 94)
fill(255,0,0)
text("screen 1",WIDTH/2,HEIGHT/2)
text("tap screen for next screen",WIDTH/2,HEIGHT/2-200)
end
function screen2()
background(95, 255, 0, 95)
fill(255,0,0)
text("screen 2",WIDTH/2,HEIGHT/2)
text("tap screen for next screen",WIDTH/2,HEIGHT/2-200)
end
function screen3()
background(0, 255, 239, 95)
fill(255,0,0)
text("screen 3",WIDTH/2,HEIGHT/2)
text("tap screen for next screen",WIDTH/2,HEIGHT/2-200)
end
--go to the next screen when the screen is touched
function touched(t)
if t.state==BEGAN then
s=s+1
--if we've got past the last screen, go back to the first
if s>#states then
s=1
end
end
end
--# Menu
--Menu example
--this example prints your choice at the left, it doesn't change the screen
--if you want to show different screens when a choice is pressed, why not look at the State or State2 examples
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"Menu") end
function setup()
end
function draw()
menu()
end
function menu()
background(0,0,200)
local w=WIDTH/2 -- set width value
local eh=HEIGHT-350 -- set height of different options
local nh=HEIGHT-500 -- eh easy, nh normal, hh hard
local hh=HEIGHT-650
pushMatrix() --store style settings
font("Zapfino") -- set font used
fontSize(48) -- set font size
fill(255,0,0) -- set font color
local menuTitle1="Main Menu" -- main title
local menuTitle2="Select Option"
text(menuTitle1,w,HEIGHT-75) -- display titles
text(menuTitle2,w,HEIGHT-200)
fill(0,255,0) -- set easy values
local t1="Easy"
text(t1,w,eh)
local w1,h1=textSize(t1) -- width and height of easy text
local t2="Normal" -- set normal values
text(t2,w,nh)
local w2,h2=textSize(t2) -- width and height of normal text
local t3="Hard" -- set hard values
text(t3,w,hh)
local w3,h3=textSize(t3) -- width and height of hard text
popStyle() --restore style settings
end
--see Touch example for how touch works
function touched(t)
if t.state==BEGAN then
--check if touch is on one of the options
if t.x>w-w1/2 and t.x<w+w1/2 and t.y>eh-h1/2 and t.y<eh+h1/2 then
print("easy option selected") -- call easy routine here
end
if t.x>w-w2/2 and t.x<w+w2/2 and t.y>nh-h2/2 and t.y<nh+h2/2 then
print("normal option selected") -- call normal routine here
end
if t.x>w-w3/2 and t.x<w+w3/2 and t.y>hh-h3/2 and t.y<hh+h3/2 then
print("hard option selected") -- call hard routine here
end
end
end
--# MultiScreen
-- multiple screen example
--this shows yet another way to manage different states of the program
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"Multi screen") end
function setup()
--set the function to use for drawing, we will change this when the user makes choices
--we can put functions into a variable because the name screen1 doesn't actually hold a function, but
--the address of the function. This address is numeric and can be stored in a variable
func=menu -- start screen
buttonTab={} -- buttons table
-- button(x,y,width,height,button name,button screen,button function)
-- buttons that show on the menu screen
table.insert(buttonTab,button(350,600,100,50,"Screen 1",menu,screen1))
table.insert(buttonTab,button(350,500,100,50,"Screen 2",menu,screen2))
table.insert(buttonTab,button(350,400,100,50,"Screen 3",menu,screen3))
table.insert(buttonTab,button(700,50,100,50,"EXIT",menu,close))
-- buttons that show on screen1
table.insert(buttonTab,button(350,600,150,50,"Google",screen1,url1))
table.insert(buttonTab,button(350,500,150,50,"twolivesleft",screen1,url2))
table.insert(buttonTab,button(350,100,150,50,"Menu",screen1,menu))
-- buttons that show on screen2
table.insert(buttonTab,button(350,600,150,50,"map quest",screen2,url3))
table.insert(buttonTab,button(350,100,150,50,"Menu",screen2,menu))
-- buttons that show on screen3
table.insert(buttonTab,button(350,600,150,50,"amazon",screen3,url4))
table.insert(buttonTab,button(350,100,150,50,"Menu",screen3,menu))
end
function draw()
background(40, 40, 50)
fill(255)
func() -- call the current function
end
--check if any of the buttons were touched
--see Touch example for more on touch
--see Snake example for more on pairs function
function touched(t) -- check if a button was pressed
if t.state==BEGAN then
for a,b in ipairs(buttonTab) do
if b:touched(t) then --see button:touched below
break
end
end
end
end
function menu()
background(58, 97, 136, 255)
fontSize(30)
text("Menu Screen",350,700)
drawButtonTab()
end
function screen1()
background(101, 43, 43, 255)
fontSize(30)
text("Screen 1",350,700)
drawButtonTab()
end
function screen2()
background(110, 165, 74, 255)
fontSize(30)
text("Screen 2",350,700)
drawButtonTab()
end
function screen3()
background(150, 144, 44, 255)
fontSize(30)
text("Screen 3",350,700)
drawButtonTab()
end
--a set of functions to act on your choices
--note how func is set to a different function, to tell the program what to do next
function url1()
openURL('http://www.google.com',true)
func=screen1 -- return to screen1
end
function url2()
openURL('http://twolivesleft.com',true)
func=screen1 -- return to screen2
end
function url3()
openURL('http://www.mapquest.com',true)
func=screen2 -- return to screen3
end
function url4()
openURL('http://www.amazon.com',true)
func=screen3 -- return to screen4
end
function drawButtonTab() -- draw selected buttons from button table
fontSize(20)
for a,b in ipairs(buttonTab) do
b:draw() --draw each button, see button:draw below
end
end
--this is an example of a class
--it controls everything about each button
button=class()
--this initialises a new button, and is given a set of inputs
function button:init(x,y,w,h,name,screen,func)
--the prefix "self" stores the variable within a special copy of the class just for this current button
self.x=x -- x position
self.y=y -- y position
self.w=w -- width
self.h=h -- height
self.name=name -- name to put on the button
self.screen=screen -- screen to draw the button on
self.func=func -- function to call when the button is pressed
end
--note it is button:draw, not button.draw
--the colon tells Codea to pass through which button it is
--then we can use the self prefix to get hold of the details for this particular button
function button:draw()
if func==self.screen then -- draw the button
fill(31, 178, 212, 255)
ellipse(self.x,self.y,self.w,self.h)
fill(255, 0, 0, 255)
text(self.name,self.x,self.y)
end
end
--similar to button:draw
--is run from the touched function above when a touch happens
function button:touched(t)
if func==self.screen then -- only check current screen button
if t.x>self.x-self.w/2 and t.x<self.x+self.w/2 and
t.y>self.y-self.h/2 and t.y<self.y+self.h/2 then
func=self.func
return true
end
return false
end
end
--# Collision
--collision example using physics objects (which will handle all the bouncing)
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"Collision") end
function setup()
b=65 -- starting value for letter A, this is the number code
--(we use numbers because then we can increase or decrease them easily)
--there are a few things to set up for each physics object
c1 = physics.body(CIRCLE,5) -- create boundary for the letter
c1.x=295
c1.y=900
c1.restitution=.8 --bounciness
c2 = physics.body(CIRCLE,50) -- create boundary for 1st circle
c2.type=STATIC --this won't move
c2.x=300
c2.y=600
c3 = physics.body(CIRCLE,50) -- create boundary for 2nd circle
c3.type=STATIC
c3.x=120
c3.y=400
end
function draw()
a=string.char(b) -- convert number code of character to a letter
background(30, 30, 30, 25)
stroke(255)
strokeWidth(1)
noFill()
--draw circles, we just use their current positions
--the physics engine calculates those automatically for us
ellipse(c2.x,c2.y,100,100) -- draw the 1st circle
ellipse(c3.x,c3.y,100,100) -- draw the 2nd circle
fill(255)
fontSize(30)
text(a,c1.x,c1.y) -- draw the letter
-- get next letter when previous gets below y position of 20
if c1.y<20 then
c1.y=900
c1.x=295
c1.linearVelocity=vec2(0,0)
b = b + 1
if b>90 then
b=65
end
end
end
--this is only needed when used in this project with many other tabs
--you can delete it if you copy the code to your own project
function cleanup()
if c1 then
c1:destroy() c1=nil
c2:destroy() c2=nil
c3:destroy() c3=nil
end
end
--# Collision2
--collision example printing data
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"Collision 2") end
-- all of this info can be found in the online manual
-- see the physics tab
function setup()
-- creates a circle that doesn't move
c1 = physics.body(CIRCLE,100) -- create body for 1st circle
c1.type=STATIC -- static means the circle doesn't move
c1.x=WIDTH/2 -- starting x,y values
c1.y=300
-- creates a circle that is influenced by gravity
c2 = physics.body(CIRCLE,50) -- create body for 2nd circle
c2.x=WIDTH/2 -- starting x,y values
c2.y=800
c2.restitution=1 -- how much the circle bounces when collided
end
function draw()
background(40,40,50)
stroke(255)
strokeWidth(1)
noFill()
ellipse(c1.x,c1.y,200,200) -- draw the 1st circle position
ellipse(c2.x,c2.y,100,100) -- draw the 2nd circle position
end
function collide(c)
if c.state==BEGAN then -- do this when the collision begins
print("\ncollision") -- \n makes Codea go to the next line down
print(c.id)
print("radius of body A ",c.bodyA.radius)
print("radius of body B ",c.bodyB.radius)
print("position of body A ",c.bodyA.x)
print("position of body A ",c.bodyA.y)
-- see physics.contact and physics.body in the reference manual
-- for other info that's available during a collision
end
end
--this is only needed when used in this project with many other tabs
--you can delete it if you copy the code to your own project
function cleanup()
if c1 then
c1:destroy() c1=nil
c2:destroy() c2=nil
end
end
--# Rotate
-- rotate example
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"Rotate") end
function setup()
w=WIDTH
w2=WIDTH/2
h=100
--draw physics edges to screen so our ball bounces
e1=physics.body(EDGE,vec2(0,h),vec2(w2,0))
e2=physics.body(EDGE,vec2(w2,0),vec2(w,h))
e3=physics.body(EDGE,vec2(w,0),vec2(w,HEIGHT))
--ball
r1=physics.body(CIRCLE,40)
r1.x=0
r1.y=500
r1.restitution=.8 --bounciness
r1.linearVelocity=vec2(210,0)
end
function draw()
background(40, 40, 50)
noFill()
stroke(255)
strokeWidth(2)
--draw lines to show edges of screen
line(0,h,w2,0)
line(w2,0,w,h)
line(w,0,w,HEIGHT)
pushMatrix() --store current location of origin (0,0) and rotation
translate(r1.x,r1.y) --move 0,0 to the position x=r1.x, y=r1.y
--so if we draw anything at 0,0 it will actually draw at r1.x, r1.y
--but the reason we do this is that all rotation happens around 0,0
--we want to rotate around the centre of our object, at r1.x, r1.y
--that is why we "translate" to that position, so rotation will be centred on our object
xx=r1.angle
rotate(xx) --whee!
ellipse(0,0,80) --draw our circle and line
line(0,0,0,38)
popMatrix() --restore previous origin position and rotation
end
--# Block
-- 3D block example
--don't expect to understand much of this if you've never worked with 3D before
--if you want to learn about it, look for 3D topics on the Wiki link in the Codea forum
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"3D block") end
function setup()
b=CreateBlock(10,20,15) --create block mesh with dimensions 10,20,15
--set up some parameters for user to play with
parameter.integer("rotateX",0,360,200)
parameter.integer("rotateY",0,360,150)
parameter.integer("rotateZ",0,360,200)
parameter.integer("Distance",0,1000,100)
print("Use the sliders above to rotate the block (drag this print area down to see all the sliders)")
end
function draw()
background(0)
perspective() --sets up 3D with (default) 45 degree angle and current screen shape
camera(0,0,0,0,0,-1000) --camera located at 0,0,0 and points at 0,0,-1000
pushMatrix()
translate(0,0,-Distance) --z is negative in OpenGL
--rotate on our three axes by the current angle, one by one
rotate(rotateX,1,0,0)
rotate(rotateY,0,1,0)
rotate(rotateZ,0,0,1)
b:draw() --draw
popMatrix()
end
--creates a block mesh
function CreateBlock(w,h,d)
local block = mesh()
--we'll centre it on 0,0,0 so it needs to be half on each side of 0
local ww,hh,dd=w/2,h/2,d/2
--define the 8 corners of our block
local v = { vec3(-ww,-hh,dd),vec3(-ww,hh,dd),
vec3(ww,-hh,dd),vec3(ww,hh,dd),
vec3(-ww,-hh,-dd),vec3(-ww,hh,-dd),
vec3(ww,-hh,-dd),vec3(ww,hh,-dd) }
--each of the 6 faces is made up of two triangles, ie a sequence of 6 corners
local faces = { v[1],v[2],v[3],v[2],v[3],v[4],
v[2],v[4],v[6],v[4],v[6],v[8],
v[1],v[2],v[5],v[2],v[5],v[6],
v[3],v[4],v[7],v[4],v[7],v[8],
v[1],v[3],v[5],v[3],v[5],v[7],
v[5],v[6],v[7],v[6],v[7],v[8] }
--splash of colour
local c = { color(255, 0, 0, 255), color(0, 255, 0, 255),
color(255, 243, 0, 255), color(0, 0, 255, 255),
color(255, 255, 255, 255), color(255, 0, 189, 255)}
local vertColors={}
local n=0
for i=1,6 do
for j=1,6 do
n=n+1
vertColors[n]=c[i]
end
end
--attach the vertices and colours to our mesh
block.vertices = faces
block.colors = vertColors
return block
end
--# Joint1
-- joint example
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"Joint 1") end
function setup()
c1 = physics.body(CIRCLE,0)
c1.x = 400
c1.y = 800
c1.restitution = 1
c1.type = STATIC
p1=physics.body(POLYGON,vec2(-10,25),vec2(-10,-25),vec2(10,-25),vec2(10,25))
p1.x=100
p1.y=800
j1 = physics.joint(REVOLUTE, c1, p1,c1.position)
end
function draw()
background(40, 40, 50)
strokeWidth(2)
line(c1.x,c1.y,p1.x,p1.y)
pushMatrix()
translate(p1.x,p1.y)
rotate(p1.angle)
local points = p1.points
for j = 1,#points do
a = points[j]
b = points[(j % #points)+1]
line(a.x, a.y, b.x, b.y)
end
popMatrix()
end
--only needed because there are other physics demos in this project, delete if you copy code elsewhere
function cleanup()
if c1 then
c1:destroy() c1=nil
p1:destroy() p1=nil
j1:destroy() j1=nil
end
end
--# Joint2
--joint example 2
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"Joint 2") end
function setup()
c1 = physics.body(CIRCLE,0)
c1.x = 400
c1.y = 1000
c1.type = STATIC
c2 = physics.body(CIRCLE,25)
c2.x = 200
c2.y = 900
c3 = physics.body(CIRCLE, 25)
c3.x = 500
c3.y = 950
c4 = physics.body(CIRCLE, 25)
c4.x = 300
c4.y = 850
p1=physics.body(POLYGON,vec2(-10,25),vec2(-10,-25),vec2(10,-25),vec2(10,25))
p1.x=400
p1.y=850
joint1 = physics.joint(REVOLUTE,c1,c2,c1.position)
joint2 = physics.joint(REVOLUTE, c2, c3,vec2(c2.x,c2.y))
joint3 = physics.joint(REVOLUTE, c3, c4,vec2(c3.x,c3.y))
joint4 = physics.joint(REVOLUTE, c4, p1,vec2(c4.x,c4.y))
end
function draw()
background(40, 40, 50)
fill(255)
strokeWidth(2)
line(c1.x,c1.y,c2.x,c2.y)
line(c2.x,c2.y,c3.x,c3.y)
line(c3.x,c3.y,c4.x,c4.y)
line(c4.x,c4.y,p1.x,p1.y)
ellipse(c1.x,c1.y,8)
ellipse(c2.x,c2.y,8)
ellipse(c3.x,c3.y,8)
ellipse(c4.x,c4.y,8)
translate(p1.x,p1.y)
rotate(p1.angle)
points = p1.points
for j = 1,#points do
a = points[j]
b = points[(j % #points)+1]
line(a.x, a.y, b.x, b.y)
end
end
--only needed because there are other physics demos in this project, delete if you copy code elsewhere
function cleanup()
if c1 then
c1:destroy() c1=nil
c2:destroy() c2=nil
c3:destroy() c3=nil
c4:destroy() c4=nil
p1:destroy() p1=nil
joint1:destroy() joint1=nil
joint2:destroy() joint2=nil
joint3:destroy() joint3=nil
joint4:destroy() joint4=nil
end
end
--# Joint3
--joint example 3
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"Joint 3") end
function setup()
a1=physics.body(CIRCLE,0)
a1.x=0
a1.y=0
a1.type=STATIC
c1=physics.body(CIRCLE,15)
c1.x=40
c1.y=700
p1=physics.body(POLYGON,
vec2(0,0),
vec2(-100,-30),
vec2(100,-30))
p1.x=0
p1.y=0
j1=physics.joint(REVOLUTE,a1,p1,vec2(0,0))
end
function draw()
background(40, 40, 50)
if c1.y<-200 then
c1.y=700
c1.x=40
c1.linearVelocity=vec2(0,0)
end
pushMatrix()
translate(250,600)
ellipse(0,0,10)
ellipse(a1.x,a1.y,10)
ellipse(p1.x,p1.y,10)
line(0,0,p1.x,p1.y)
ellipse(c1.x,c1.y,c1.radius*2)
noFill()
stroke(255)
strokeWidth(2)
xx=p1.angle
rotate(xx)
line(0,0,-100,-30)
line(-100,-30,100,-30)
line(100,-30,0,0)
popMatrix()
end
--only needed because there are other physics demos in this project, delete if you copy code elsewhere
function cleanup()
if a1 then
a1:destroy() a1=nil
c1:destroy() c1=nil
p1:destroy() p1=nil
j1:destroy() j1=nil
end
end
--# Mortgage
-- mortgage calculator
--delete the next line if you copy this to your own project
if localise then PN=PN+1 localise(PN,"Mortgage") end
function setup()
boxTab={} -- table of input/output boxes
-- x,y,w,h,type,text
table.insert(boxTab,input(100,500,120,30,1,"Loan $ amount"))
table.insert(boxTab,input(300,500,120,30,1,"Yearly % ( 5%=5 )"))
table.insert(boxTab,input(500,500,120,30,1,"Number of years"))
table.insert(boxTab,input(300,400,120,30,2,"Monthly payment"))
table.insert(boxTab,input(500,400,120,30,2,"Total payments"))
end
function draw()
background(34, 74, 82, 255) -- screen color
fill(255,0,0) -- set color to red
pushStyle()
fontSize(40)
text("MORTGAGE CALCULATOR",WIDTH/2,HEIGHT-50) -- draw text
popStyle()
fill(224, 149, 127, 255) -- set color
text("( Tap each box to input values )",WIDTH/2,HEIGHT-100) -- draw text
for a,b in pairs(boxTab) do -- loop thru table
b:draw() -- draw each box
end
amt=tonumber(boxTab[1].val) -- starting amount
int=tonumber(boxTab[2].val/100) -- yearly interest
year=tonumber(boxTab[3].val) -- number of years
-- perform interest calculation
i=int/12 -- interest per month
n=year*12 -- total months
w=(1+i)^n
m=amt*i*w/(w-1) -- calculate monthly amount
boxTab[4].val=string.format("%.2f",m) -- save monthly payment
boxTab[5].val=string.format("%.2f",m*n) -- save total payments
end
function touched(t) -- check which box is selected
for nbr,box in pairs(boxTab) do -- loop thru table
if box:touched(t) then -- box touched
return -- dont check other boxes, exit function
end
end
end
function keyboard(k)
for nbr,box in pairs(boxTab) do -- loop thru table
box:keyboard(k) -- get input from box
end
end
input=class()
function input:init(x,y,w,h,type,txt)
self.x=x -- x position
self.y=y -- y position
self.w=w -- width
self.h=h -- height
self.type=type -- 1=input box 2=output box
self.txt=txt -- text to show above box
self.val="0" -- data keyed in box
self.sel=false -- box selected true/false
end
function input:draw()
pushStyle()
rectMode(CORNER)
textMode(CORNER)
fill(0) -- set background for box
if self.sel then -- set selected color for box
fill(105, 101, 31, 255)
end
stroke(255, 66, 0, 255) -- box outline color
strokeWidth(2) -- outline size
rect(self.x,self.y,self.w,self.h) -- draw box
fill(255) -- set text color
text(self.txt,self.x,self.y+self.h) -- box name
text(self.val,self.x+4,self.y+4) -- box text
popStyle()
end
function input:keyboard(k)
if self.sel then
if k==BACKSPACE then -- backspace key pressed
str=str:sub(1,str:len()-1) -- remove last digit
if str=="" then -- blank
str="0" -- make 0
end
elseif k>="0" and k<="9" or k=="." then -- only digits 1 thru 9
if str:sub(1,1)=="0" then -- check if leading 0
str="" -- clear leading 0
end
str=str..k -- update keyed value
end
self.val=str -- save keyed value
end
end
function input:touched(t)
if t.state==BEGAN then
if not isKeyboardShowing() then
showKeyboard() -- show keyboard if its not displayed
end
str="0" -- clear value
for z=1,#boxTab do -- clear selected flag for all boxes
boxTab[z].sel=false
end
-- check which box was selected
if t.x>self.x and t.x<self.x+self.w and
t.y>self.y and t.y<self.y+self.h and self.type==1 then
self.val="0" -- reset val
self.sel=true -- set selected flag
return true -- a box was selected
end
end
return false -- no box was selected
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment