Does anyone have any code for a (preferably infinite scrolling) horizontal carousel they’d be happy to share?
Like this?
--Panorama shader
function setup()
--create background scenery image
--make it a little wider than the screen so it doesn't start repeating too soon
scenery=image(WIDTH*1.2,150)
--draw some stuff on it
setContext(scenery)
pushStyle()
strokeWidth(1)
stroke(75)
fill(150)
local x=0
rectMode(CORNER)
while x<scenery.width do
local w=math.random(25,100)
local h=math.random(50,150)
rect(x,0,w,h)
x=x+w
end
popStyle()
setContext()
--create mesh
m=mesh()
m:addRect(scenery.width/2,scenery.height/2,scenery.width,scenery.height)
m:setColors(color(255))
m.texture=scenery
m.shader=shader(PanoramaShader.vertexShader,PanoramaShader.fragmentShader)
--initialise offset
offset=0
output.clear()
print("Scroll an image continously")
print("This is useful for a side scrolling game to create the illusion of movement")
end
function draw()
background(40, 40, 50)
offset=offset+1
m.shader.offset=offset/scenery.width
m:draw()
--sprite(scenery,WIDTH/2,100)
end
PanoramaShader = {
vertexShader = [[
uniform mat4 modelViewProjection;
uniform float offset;
attribute vec4 position;
attribute vec4 color;
attribute vec2 texCoord;
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
void main()
{
vColor=color;
vTexCoord = vec2(texCoord.x+offset,texCoord.y);
gl_Position = modelViewProjection * position;
}
]],
fragmentShader = [[
precision highp float;
uniform lowp sampler2D texture;
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;
void main()
{
lowp vec4 col = texture2D( texture, vec2(mod(vTexCoord.x,1.0), mod(vTexCoord.y,1.0)));
gl_FragColor = col;
}
]]}
I’ll give it a whiz in the morning and let you know - thanks
Not sure what you mean by Carousel. Here’s a scrolling background.
displayMode(FULLSCREEN)
supportedOrientations(LANDSCAPE_ANY)
function setup()
tab1={readImage("Small World:Tree 1"),readImage("Small World:Tree 2"),readImage("Small World:Tree 3"),
readImage("Small World:House White")}
tab={}
for z=150,1,-1 do
table.insert(tab,vec3(math.random(WIDTH),z*4+200,math.random(4)))
end
end
function draw()
background(105, 88, 31, 255)
for a,b in pairs(tab) do
b.x=b.x+2+(500-b.y)/300
if b.x>WIDTH+50 then
b.x=-50
end
sprite(tab1[b.z],b.x,b.y,a*.4)
end
end
What’s a carousel? I’d use translate for scrolling.
Thanks for the examples they’re very useful but that wasn’t exactly what I was referring to.
I want to create a control that will act as a container for a number of “pages”, each page will contain a number of other interactive elements.
You can swipe / scroll left & right (or up / down) to view different pages.
Carousels are the name usually given to these type of controls (especially in the web world) based on the way they go round and round, you often see them used on level select screens in games.
eg.
(the image is nothing to do with me - just some random one I pulled from Google images).
@TechDojo Is this closer to what you want. I didn’t spend a lot of time on this just in case it’s not. I used 1 image, but they could be different. You can scroll each area.
displayMode(FULLSCREEN)
supportedOrientations(LANDSCAPE_ANY)
function setup()
dx1,dy1=0,0
dx2,dy2=0,0
dx3,dy3=0,0
dx4,dy4=0,0
end
function draw()
background(40, 40, 50)
clip(50,300,200,200)
sprite("Cargo Bot:Startup Screen",150+dx1,450+dy1)
clip(300,300,200,200)
sprite("Cargo Bot:Startup Screen",400+dx2,450+dy2)
clip(550,300,200,200)
sprite("Cargo Bot:Startup Screen",650+dx3,450+dy3)
clip(800,300,200,200)
sprite("Cargo Bot:Startup Screen",900+dx4,450+dy4)
end
function touched(t)
if t.state==MOVING then
if t.x>50 and t.x<250 and t.y>300 and t.y<500 then
dx1=dx1+t.deltaX
dy1=dy1+t.deltaY
end
if t.x>300 and t.x<500 and t.y>300 and t.y<500 then
dx2=dx2+t.deltaX
dy2=dy2+t.deltaY
end
if t.x>550 and t.x<750 and t.y>300 and t.y<500 then
dx3=dx3+t.deltaX
dy3=dy3+t.deltaY
end
if t.x>800 and t.x<1000 and t.y>300 and t.y<500 then
dx4=dx4+t.deltaX
dy4=dy4+t.deltaY
end
end
end
Hi Dave,
Thanks, but that’s not quite, actually that’s kind of inverse what I was after.
I’ll have a bang at it at lunch today and share my attempt later.
Here’s a quick example of what I was thinking of - although this one doesn’t do the infinite wrapping at each end (swipe left / right to change slides)
Carousel = class()
function Carousel:init(options)
print("Carousel:init()")
self.images = options
for i=1,#self.images do
self.images[i].baseX = self.images[i].page * WIDTH
end
self.page = 0
self.offset = 0
self.numImages = #self.images
self.tx, self.ty = 0,0 -- position of touch for swipe detection
self.tid = 0 -- ID (prevent multitouch messing things up)
self.swiping = false
end
function Carousel:draw()
local img
pushMatrix(); pushStyle();
spriteMode(CENTER)
for i=1,self.numImages do
img = self.images[i]
resetMatrix()
translate(img.baseX,0)
translate(self.offset,0)
sprite(img.image,img.ox,img.oy)
end
popStyle(); popMatrix()
end
function Carousel:swipe(offset)
local dest = self.offset + offset
self.swiping = true
tween(0.333,self,{offset = dest},tween.easing.linear,
function()
self.swiping = false
end)
end
function Carousel:swipeLeft()
print("SWIPE LEFT")
self:swipe(WIDTH)
end
function Carousel:swipeRight()
print("SWIPE RIGHT")
self:swipe(-WIDTH)
end
function Carousel:touched(t)
-- Very simple check for horizontal swipes
if not self.swiping then
if t.state == BEGAN and self.tid == 0 then
self.tid,self.tx,self.ty = t.id,t.x,t.y
end
if t.state == ENDED and self.tid == t.id then
local dx = t.x - self.tx
if dx > 20 then self:swipeLeft()
elseif dx < -20 then self:swipeRight()
end
self.tid = 0
end
end
end
-- -----------------------
displayMode(FULLSCREEN)
supportedOrientations(LANDSCAPE_ANY)
local carousel
local CX,CY = WIDTH/2,HEIGHT/2
local OY = CY - 100
function setup()
carousel = Carousel({
{image = "Cargo Bot:Pack Easy", ox=CX, oy=OY, page=0 },
{image = "Cargo Bot:Pack Medium", ox=CX, oy=OY, page=1 },
{image = "Cargo Bot:Pack Hard", ox=CX, oy=OY, page=2 },
{image = "Cargo Bot:Pack Impossible", ox=CX, oy=OY, page=3 },
{image = "Cargo Bot:Pack Crazy", ox=CX, oy=OY, page=4 },
})
end
function draw()
spriteMode(CENTER)
sprite("Cargo Bot:Opening Background",CX,CY,WIDTH,HEIGHT)
sprite("Cargo Bot:Cargo Bot Title",CX,HEIGHT-200)
sprite("Cargo Bot:Command Left",100,OY)
sprite("Cargo Bot:Command Right",WIDTH-100,OY)
carousel:draw()
end
function touched(t)
carousel:touched(t)
end
Surely it’s a simple case of testing if you’ve gone past the end and resetting the counter to the start again?
@TechDojo Here’s something I already had. I modified it to allow infinite scrolling left or right and added the table of sprites to display.
displayMode(FULLSCREEN)
supportedOrientations(PORTRAIT_ANY)
function setup()
tab={"Planet Cute:Character Boy","Planet Cute:Character Cat Girl",
"Planet Cute:Character Horn Girl","Planet Cute:Character Pink Girl",
"Planet Cute:Character Princess Girl","Planet Cute:Enemy Bug",
"Planet Cute:Gem Blue","Planet Cute:Gem Green"}
dx=0
page=0
dir=0
cc=1
check(0)
end
function check(v)
page=page+v
dir=30*v
cc=cc+v
if cc>#tab then
cc=1
end
if cc<1 then
cc=#tab
end
cc2=cc
cc1=cc2-1
if cc1<1 then
cc1=#tab
end
cc3=cc2+1
if cc3>#tab
then
cc3=1
end
end
function draw()
background(0)
w=WIDTH*(page-1)
sprite(tab[cc1],WIDTH/2+dx-w,HEIGHT/2)
w=WIDTH*page
sprite(tab[cc2],WIDTH/2+dx-w,HEIGHT/2)
w=WIDTH*(page+1)
sprite(tab[cc3],WIDTH/2+dx-w,HEIGHT/2)
if scroll then
dx=dx+dir
if dir>0 and dx>page*WIDTH or dir<0 and dx<page*WIDTH then
dx=page*WIDTH
scroll=false
end
end
end
function touched(t)
if t.state==MOVING then
dx=dx+t.deltaX
dir=t.deltaX
end
if t.state==ENDED then
scroll=true
if dir>0 then
check(1)
elseif dir<0 then
check(-1)
end
end
end
@TechDojo Here’s another version. You would have different tables for each view. To save time, I just used the same table for each one. Swipe left or right on an object.
displayMode(FULLSCREEN)
supportedOrientations(LANDSCAPE_ANY)
function setup()
rectMode(CENTER)
tab={"Planet Cute:Character Boy","Planet Cute:Character Cat Girl",
"Planet Cute:Character Horn Girl","Planet Cute:Character Pink Girl",
"Planet Cute:Character Princess Girl","Planet Cute:Enemy Bug",
"Planet Cute:Gem Blue","Planet Cute:Gem Green"}
car={}
table.insert(car,carousel(150,400))
table.insert(car,carousel(400,400))
table.insert(car,carousel(650,400))
table.insert(car,carousel(900,400))
end
function draw()
background(60, 184, 228, 255)
for a,b in pairs(car) do
b:draw()
end
end
function touched(t)
for a,b in pairs(car) do
b:touched(t)
end
end
carousel=class()
function carousel:init(x,y)
self.x=x
self.y=y
self.cc=1
self.dir=0
end
function carousel:draw()
stroke(255)
strokeWidth(8)
fill(222, 186, 140, 255)
rect(self.x,self.y,200,300)
sprite(tab[self.cc],self.x,self.y)
end
function carousel:touched(t)
if t.x>self.x-100 and t.x<self.x+100 and t.y>self.y-150 and t.y<self.y+150 then
if t.state==BEGAN then
self.dir=t.x
end
if t.state==ENDED then
if t.x>self.dir then
self:check(1)
else
self:check(-1)
end
end
end
end
function carousel:check(v)
self.cc=self.cc+v
if self.cc>#tab then
self.cc=1
elseif self.cc<1 then
self.cc=#tab
end
end
Hey @TechDojo try this out. I think it’s what you’re going for, based on your picture, and it has infinite scrolling too
displayMode(FULLSCREEN)
supportedOrientations(LANDSCAPE_ANY)
function setup()
carousel = Carousel()
end
function draw()
carousel:draw()
end
function touched(touch)
if touch.state == BEGAN then tchId = touch.id end
if tchId == touch.id then carousel:touched(touch) end
end
Carousel = class()
function Carousel:init()
tab = {
"Cargo Bot:Pack Tutorial","Cargo Bot:Pack Tutorial","Cargo Bot:Pack Tutorial",
"Cargo Bot:Pack Easy","Cargo Bot:Pack Easy","Cargo Bot:Pack Easy",
"Cargo Bot:Pack Medium","Cargo Bot:Pack Medium","Cargo Bot:Pack Medium",
"Cargo Bot:Pack Hard","Cargo Bot:Pack Hard","Cargo Bot:Pack Hard",
"Cargo Bot:Pack Crazy","Cargo Bot:Pack Crazy","Cargo Bot:Pack Crazy",
"Cargo Bot:Pack Impossible","Cargo Bot:Pack Impossible","Cargo Bot:Pack Impossible"
}
local n = #tab
self.scroll = 0
self.limit = 0
self.perPage = 3
self.pageNum = math.ceil(n/self.perPage)
self.page = 1
self.vel = 0
while #tab % self.perPage ~= 0 do
tab[#tab+1] = image(0,0)
end
end
function Carousel:draw()
background(40,40,50)
if self.page > self.pageNum then self.page = 1 end
if self.page < 1 then self.page = self.pageNum end
self.limit = (self.page-1)*WIDTH
if self.swipe == true then
if self.scroll ~= self.limit then
self.scroll = self.scroll - (self.scroll-self.limit)/5
end
self.vel = 0
self.scroll = self.scroll + self.vel
end
pushMatrix()
translate(-self.scroll,0)
for i,v in pairs(tab) do
sprite(v,i*WIDTH/self.perPage-WIDTH/self.perPage/2,HEIGHT/2)
end
for i = 1,self.perPage do
local x = self.pageNum*WIDTH
local v = tab[i]
sprite(v,x+i*WIDTH/self.perPage-WIDTH/self.perPage/2,HEIGHT/2)
end
for i = 1,self.perPage do
local x = -WIDTH
local v = tab[#tab+i-self.perPage]
sprite(v,x+i*WIDTH/self.perPage-WIDTH/self.perPage/2,HEIGHT/2)
end
popMatrix()
pushStyle()
for i = 1,self.pageNum do
local s = self.pageNum*50/2+25
noStroke()
if i == self.page then
fill(200,255)
ellipse(WIDTH/2-s+i*50,75,40)
else
fill(100,255)
ellipse(WIDTH/2-s+i*50,75,30)
end
end
popStyle()
end
function Carousel:touched(touch)
if touch.state == BEGAN then
self.vel = nil
self.temp1 = nil
self.temp2 = nil
end
if touch.state == ENDED and touch.tapCount > 0 then
for i = 1,self.pageNum do
local s = self.pageNum*50/2+25
local x,y = WIDTH/2-s+i*50,75
local v = vec2(touch.x,touch.y)-vec2(x,y)
if v:len() < 20 then self.page = i end
end
end
if touch.state ~= ENDED then
self.swipe = false
self.scroll = self.scroll - touch.deltaX
if self.scroll < self.limit - WIDTH then self.scroll = self.limit - WIDTH end
if self.scroll > self.limit + WIDTH then self.scroll = self.limit + WIDTH end
else
self.swipe = false
end
if touch.state == ENDED then
self.swipe = true
if self.vel > 5 or self.scroll > self.limit + 200 then self.page = self.page + 1 end
if self.vel < -5 or self.scroll < self.limit - 200 then self.page = self.page - 1 end
if self.page > self.pageNum then
self.page = 1
self.scroll = self.scroll - self.pageNum*WIDTH
end
if self.page < 1 then
self.page = self.pageNum
self.scroll = self.scroll + self.pageNum*WIDTH
end
self.limit = (self.page-1)*WIDTH
end
self.vel = self.temp1 or -touch.deltaX
self.temp1 = self.temp2 or -touch.deltaX
self.temp2 = -touch.deltaX
end
EDIT: I changed some of the code so you can switch pages by tapping the circles at the bottom
EDIT 2: I added a new variable self.perPage
that lets you change the number of items on each screen. 1, 2, 3, and 4 all look pretty good, but try anything higher than that and they start to overlap
No problem! Now that I’ve written the code for it, I’ll probably use it in a lot of my other projects as well, so thanks for giving me the idea