This is a page controller designed to mimic the behaviour of things like the home screen on your ipad. It is still work in progress but it is usable as it is. There are instructions for use in the HowTo tab. If you have any questions, feedback or suggestions please comment below.
--# Main
function setup()
pgCtrl=PageController(6)
print("swipe about and press the buttons!")
end
function draw()
pgCtrl:update()
background(0)
spriteMode(CENTER)
sprite("Cargo Bot:Game Lower BG",WIDTH/2,HEIGHT/2,WIDTH,HEIGHT)
pushMatrix()
translate(pgCtrl:getTranslateAmount())
fill(0)
textMode(CENTER)
fontSize(50)
for i=1,6 do
local W=300
if i==pgCtrl:currentPage() then W=400 end
sprite("Cargo Bot:Codea Icon",WIDTH*(i-0.5),HEIGHT/2,W)
text(i,WIDTH*(i-0.5),HEIGHT/2)
end
popMatrix()
spriteMode(CORNER)
sprite("Cargo Bot:Command Right",WIDTH-50,0,50)
sprite("Cargo Bot:Command Left",0,0,50)
text("page "..pgCtrl:currentPage(),WIDTH/2,HEIGHT-50)
pgCtrl:drawPageCircs(30)
end
function touched(touch)
local translatedTouch=pgCtrl:touched(touch)
if touch.state==BEGAN then
if pointInRect(touch.x,touch.y,0,0,50,50) then
pgCtrl:goRight()
end
if pointInRect(touch.x,touch.y,WIDTH-50,0,50,50) then
pgCtrl:goLeft()
end
local W,H=400,400
for i=1,6 do
if pointInRect(translatedTouch.x,translatedTouch.y,WIDTH*(i-0.5)-W/2,HEIGHT/2-H/2,W,H) then
print("you touched button: "..i)
end
end
end
end
function pointInRect(ptx,pty,x,y,w,h)
return (x<=ptx and ptx<=x+w and y<=pty and pty<=y+h)
end
--# PageController
PageController = class()
function PageController:init(npgs,page,width)
self.numPages=npgs
self.pageW=w or WIDTH
self.offset=((page or 1)-1)*self.pageW
self.min=0
self.max=self.pageW*(self.numPages-1)
self.alignTw=nil
self.swipeSpeed=800
self.tweenDelay=0.3
self.touchInfo={startPos=0,startTime=0,time=0,dist=0,speed=0}
self.touchDown=false
end
function PageController:update()
if self.alignTw==nil and self.touchDown==false then
self:snap()
end
--translate(-self.offset,0)
end
function PageController:getTranslateAmount()
return -self.offset,0
end
function PageController:drawPageCircs(s)
local r=s or 20
local w=(self.numPages*2-1)*r
noStroke()
fill(255)
ellipseMode(CORNER)
for i=1,self.numPages do
local x=(self.pageW/2-w/2)+(r*(i-1)*2)
if i==
math.min(self.numPages,math.max(1,math.floor((self.offset+self.pageW)/self.pageW+0.5))) then
fill(255,255)
else
fill(255,100)
end
ellipse(x,0+r,r,r)
end
end
function PageController:touched(t)
if t.state==BEGAN then
self.touchInfo.startPos=t.x
self.touchInfo.startTime=ElapsedTime
if self.alignTw then
tween.stop(self.alignTw)
self.alignTw=nil
end
self.touchDown=true
end
if (ElapsedTime-self.touchInfo.startTime)>0.1 then
local move=-t.deltaX
local factr=20
if self.offset<=self.min and move<0 then
local diff=self.min-self.offset
if diff~=0 then
move=move/diff*factr
end
elseif self.offset>=self.max and move>0 then
local diff=self.offset-self.max
if diff~=0 then
move=move/diff*factr
end
end
self.offset = self.offset +move
end
if t.state==ENDED then
self.touchDown=false
self.touchInfo.dist=(t.x-self.touchInfo.startPos)
self.touchInfo.time=ElapsedTime-self.touchInfo.startTime
self.touchInfo.speed=self.touchInfo.dist/self.touchInfo.time
if self.touchInfo.speed>self.swipeSpeed and self:currentPage()>1 then
self:goTo(self:currentPage()-1)
elseif self.touchInfo.speed<-self.swipeSpeed and self:currentPage()<self.numPages then
self:goTo(self:currentPage()+1)
end
end
local tch=self:makeTouch(t)
tch.x = tch.x +self.offset
tch.prevX = tch.prevX +self.offset
return tch
end
function PageController:goTo(num)
if self.alignTw then tween.stop(self.alignTw)end
self.alignTw=tween(0.3,self,{offset=(num-1)*self.pageW},
nil,function(obj) obj.alignTw=nil end,self)
end
function PageController:snap()
self.alignTw=tween(0.2,self,{offset=(self:currentPage()-1)*self.pageW},
nil,function(obj) obj.alignTw=nil end,self)
end
function PageController:currentPage()
return math.floor(self.offset/self.pageW+0.5)+1
end
function PageController:goLeft()
local t=self:currentPage()+1
if t<=self.numPages then
self:goTo(t)
end
end
function PageController:goRight()
local t=self:currentPage()-1
if t>=1 then
self:goTo(t)
end
end
function PageController:makeTouch(touch)
local t={}
t.x=touch.x;t.y=touch.y;t.deltaX=touch.deltaX;t.deltaY=touch.deltaY;t.prevX=touch.prevX;
t.prevY=touch.prevY;t.id=touch.id;t.state=touch.state;t.tapCount=touch.tapCount;
return t
end
--# HowTo
--[[
PageController
this class manages menus and other page based scrolling interfaces. it is based on the apple
home screen.
How to use:
-define a PageController and pass it:
a number of pages,
the page it will start on(default 1),
and the width of each page(default is the screen width: WIDTH)
~~
pgCtrl=PageController(6,2,WIDTH)
~~
-in draw, call the update method
~~
pgCtrl:update()
~~
before you draw elements that will move when you scroll the pages do:
~~
translate(pgCtrl:getTranslateAmount())
~~
this will move them to the right position
objects should be placed relative to the first page so an object on page 'n' should be at:
x=pgCtrl.pageW*(n-1)+x_position_on_page,y=y_position_on_page
you can also call the drawPageCircs method to draw the circles which indocate the page you
are on, you can optionaly pass it the circle radius
~~
pgCtrl:drawPageCircs(10)
~~
-in the touched(touch)function call the touched method for the page controller. this will
deal with scrolling the pages. it returns a touch that has been translated relative to the current
page.
~~
local translatedTouch=pgCtrl:touched(touch)
~~
use translatedTouch for objects that scroll with the page controller and normal touch for ones
that don't
-call the goTo method to go to the specified page
~~
pgCtrl:goTo(3)
~~
-call the goRight and goLeft methods to move one page right or left
~~
pgCtrl:goRight()
pgCtrl:goLeft()
~~
-call the currentPage method to get the current page number
~~
pgCtrl:currentPage()
~~
--]]