Skip to content

Instantly share code, notes, and snippets.

@tarrouye
Last active August 29, 2015 14:04
Show Gist options
  • Save tarrouye/5f5f4939ffef4eb13380 to your computer and use it in GitHub Desktop.
Save tarrouye/5f5f4939ffef4eb13380 to your computer and use it in GitHub Desktop.
--# Main
-- Page Controller class for Codea
-- By JakAttak
displayMode(FULLSCREEN)
function setup()
font("HelveticaNeue-UltraLight")
local title = Title("Page Controller")
page = PageController(title, page2, { draw = page3, touched = tpage3 })
end
function draw()
background(255)
page:draw()
end
function touched(t)
page:touched(t)
end
-- Example pages
function page2()
pBackground(0, (noise(1000+ElapsedTime/100)+1.5)*128, (noise(1000+ElapsedTime/10)+1.5)*128, 255)
fontSize(40) fill(0, 0, 0, 255)
text("Hey, look, it's Page 2", WIDTH / 2, HEIGHT / 2)
end
function page3()
pBackground(255, 100, 100, 255)
stroke(0, 0, 0, 255) strokeWidth(2) if fillEllipse then fill(stroke()) else noFill() end
ellipse(WIDTH / 2, HEIGHT / 4, WIDTH / 4)
fontSize(40) fill(255, 255, 255, 255) textAlign(CENTER)
text("Page 3\n\nDemonstrates passing a table\n\nTry touching the ellipse", WIDTH / 2, HEIGHT / 1.5)
end
function tpage3(t)
if vec2(t.x, t.y):dist(vec2(WIDTH / 2, HEIGHT / 4)) <= WIDTH / 8 and t.state ~= ENDED then
fillEllipse = true
return true
else
fillEllipse = false
end
end
--# PageController
PageController = class()
function PageController:init(...)
self.pages = { ... }
self:managePages()
self.toSwitch = WIDTH / 4
self.timePerPage = 1
self.indicator = math.max(WIDTH, HEIGHT) / 100
self.page, self.scroll, self.scrollo, self.locked = 1, 0, 0, false
end
function PageController:managePages()
for i, page in ipairs(self.pages) do
if typeOf(page) == "table" then
page.draw = page.draw or function() end
page.touched = page.touched or function() end
elseif typeOf(page) == "class" then
local dfun = page.draw or function() end
page.draw = function() dfun(page) end
local tfun = page.touched or function() end
page.touched = function(touch) tfun(page, touch) end
elseif typeOf(page) == "function" then
self.pages[i] = { draw = page, touched = function() end }
else
self.pages[i] = nil
end
end
end
function PageController:draw()
-- Draw pages that should be shown
pushMatrix()
translate(self.scrollo, 0)
if self.pages[self.page] ~= nil then
pushStyle()
self.pages[self.page].draw()
popStyle()
end
if self.pages[self.page - 1] ~= nil and self.scroll > 0 then
pushMatrix()
translate(-WIDTH, 0)
pushStyle()
self.pages[self.page - 1].draw()
popStyle()
popMatrix()
end
if self.pages[self.page + 1] ~= nil and self.scroll < 0 then
pushMatrix()
translate(WIDTH, 0)
pushStyle()
self.pages[self.page + 1].draw()
popStyle()
popMatrix()
end
popMatrix()
-- Draw page indicators
local w = self.indicator * (#self.pages * 2 - 1)
local x = (WIDTH / 2) - (w / 2) + self.indicator / 2
for p = 1, #self.pages do
if p == self.page then fill(255)
else fill(255, 127) end
ellipse(x, self.indicator, self.indicator)
x = x + self.indicator * 2
end
end
function PageController:closestPage()
local closest = self.page
if self.scrollo > self.toSwitch and self.page > 1 then
closest = self.page - 1
elseif self.scrollo < -self.toSwitch and self.page < #self.pages then
closest = self.page + 1
end
return closest
end
function PageController:touched(t)
-- Handle touching on pages
if self.scrollo == 0 then
if self.pages[self.page] ~= nil and self.pages[self.page].touched(t) == true then
return -- If touched something then no scrolling
end
end
-- No scrolling when locked
if self.locked then return end
-- Stop tween when dragging
if self.releasing ~= nil then
tween.stop(self.releasing)
end
-- Scroll from drag
self.scroll = self.scroll + t.deltaX
local min = self.pages[self.page].pcSlideMin or 0
local off = math.max(0, math.abs(self.scroll) - min)
self.scrollo = off * math.sign(self.scroll)
-- Tweens to closest page
if t.state == ENDED then
local closestPage = self:closestPage()
local target = (self.page - closestPage) * WIDTH
if closestPage ~= self.page then self.locked = true end
local dur = (math.abs(self.scrollo) / (self.toSwitch)) / ((WIDTH / self.toSwitch) * self.timePerPage)
self.releasing = tween(dur, self, { scrollo = target, scroll = target }, tween.easing.cubicOut, function()
self.page = closestPage
self.scroll = 0
self.scrollo = 0
self.releasing = nil
self.locked = false
end)
end
end
-- Helper functions
function typeOf(x)
-- Extended type function
if x == nil then
return 'nil'
end
if type(x) == 'table' and x.is_a then
return('class')
end
local txt
if typeTable == nil then
typeTable = {
[getmetatable(vec2()).__index ] = 'vec2',
[getmetatable(vec3()).__index ] = 'vec3',
[getmetatable(color()).__index ] = 'color',
[getmetatable(image(1,1)).__index ] = 'image',
[getmetatable(matrix()).__index] = 'matrix',
[getmetatable(mesh()).__index ] = 'mesh' ,
[getmetatable(physics.body(CIRCLE, 1)).__index] = 'physics body',
}
end
local i = getmetatable(x)
if i then
txt = typeTable[i.__index]
end
if txt then
return txt
end
txt = type(x)
return txt
end
math.sign = function(n)
if n < 0 then
return -1
end
return 1
end
function pBackground(...)
-- Called same as background, draws a rect instead so each page can have individual background
pushStyle()
rectMode(CORNERS)
fill(...)
rect(-WIDTH / 768, -WIDTH / 768, WIDTH + WIDTH / 768, HEIGHT + WIDTH / 768)
popStyle()
end
--# Title
-- An example of using a class with the Page Controller
Title = class()
function Title:init(name)
fontSize(WIDTH / 10) fill(255, 255, 255, 255)
local w, h = textSize(name)
local timg = image(w, h) setContext(timg)
text(name, w / 2, h / 2)
setContext()
self.m = mesh()
self.m.texture = timg
self.m:addRect(WIDTH / 2, HEIGHT / 2, w, h)
self.m.shader = shader("Effects:Ripple")
self.m.shader.freq = 0.08
end
function Title:draw()
pBackground(0, 128, 255)
self.m.shader.time = ElapsedTime
self.m:draw()
fontSize(WIDTH / 30) fill(255, 255, 255, 255)
text("(swipe or drag to use)", WIDTH / 2, HEIGHT / 4)
end
function Title:touched(touch)
-- Codea does not automatically call this method
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment