Parallaxing

1 quick question, is it possible to designate a set background without having to add camera?

Again thanks you rock! [import]uid: 72845 topic_id: 35475 reply_id: 143486[/import]

What sort of thing do you mean by “designate a set background”? [import]uid: 147322 topic_id: 35475 reply_id: 143495[/import]

I want to have a layer (background) that is a fixed position. no matter the boundaries of the camera view. [import]uid: 72845 topic_id: 35475 reply_id: 143501[/import]

For that, you can make layer 8’s parallax ratio 0 and add all of your background to it.
[lua]
camera:layer(8).parallaxRatio=0
[/lua]

Caleb :slight_smile: [import]uid: 147322 topic_id: 35475 reply_id: 143505[/import]

Awesome! After messing around with it I’ve got a few more questions. Is it possible to look around with your finger by swiping the screen and also be able to follow a character once you press a button? And could you explain a little more about setting boundaries? For instance, how to set the boundary to be the size of the screen, or 2 times the size of the screen.

Thanks again, you’re restoring my faith in this project : ) [import]uid: 72845 topic_id: 35475 reply_id: 143638[/import]

Glad you’re liking it :slight_smile:

Look Around With Finger -
My best idea for this is to make an invisible focus object that’s clamped inside of the camera’s bounds and when you swipe, move the invisible object accordingly.

Focus Object on Button Touch -
Simple :slight_smile: Just use the :setFocus() inside of your button listener:
[lua]
–Using widget
local cameraBtn=widget.newButton{
default=“button.png”,
over=“button-over.png”,
onRelease=function() camera:setFocus(guy) end
}
[/lua]
Or something to that effect.

Camera Bounds Explanation -
Bounds are values that clamp the camera’s tracking range to a box. You set them with the setBounds function, which has four arguments - x1, y1, x2, and y2:
[lua]
camera:setBounds(x1, y1, x2, y2)
[/lua]
The x1 argument is the left side of the camera’s bounding box; y1 is the top of the camera’s bounding box; x2 is the right side of the camera’s bounding box; y2 is the bottom of the camera’s bounding box. By setting bounds, you’re telling the camera not to track the focus if it goes outside the bounds. But you must consider one thing -


Please note that the bounds go according to the X and Y of the object - not the sides of the camera view. So if you have an object at the very far left of the bounds, and the camera has no offsetX, the view will show half the screen size to the left of the object. You can see what I mean with this image: https://www.dropbox.com/s/1661np6bxy8n9t4/diagram.png

So there’s an explanation of bounds.

And, of course, simply use “false” (without quotes) as the first argument to stop the camera from having bounds at all.

Let me know how you get on :slight_smile:

Caleb [import]uid: 147322 topic_id: 35475 reply_id: 143709[/import]

Thanks! I think I’m getting the hang of it. I noticed one thing though when I tried to add my other code to this new code. My problem is I have a button that creates (in this case a spring) object, and when I move my character the spring object moves with my character instead of staying on the screen where I positioned it. Is it possible to make the newly created object stay where I position it and still have my character interact with it. IE Click button > position spring > character jumps on to spring and bounces?

Here’s my existing spring code

[code]
–new spring code
_W = display.contentWidth
_H = display.contentHeight
–Our variable that contains number of springs
local springCount = 0
–Our button,that needs to be touched
local button = display.newImage( “springicon.png” )

button.x = display.contentWidth / 1.04
button.y = display.contentHeight / 12

– bounce function
local function bounce(obj,minScale,maxScale,time)
local oldXScale,oldYScale = obj.xScale, obj.yScale
local minScale = minScale or 0.8
local maxScale = maxScale or 1.2
local time = time or 100
if not obj.isBouncing then
obj.isBouncing = true
transition.to(obj,{time=time,xScale=maxScale,yScale=minScale,transition=easing.inQuad,onComplete=function()
transition.to(obj,{time=time,xScale=minScale,yScale=maxScale,transition=easing.outQuad,onComplete=function()
transition.to(obj,{time=time,xScale=oldXScale,yScale=oldYScale,onComplete=function() obj.isBouncing = false end})
end})
end})
end
end

–Function to move spring, use later in another function
local function move_spring(event)
event.target.x = event.x
event.target.y = event.y
if event.phase == “began” or event.phase == “ended” or event.phase == “cancelled” then
bounce(event.target)
end
end

– collision listener function
local function onLocalCollision( self, event )
if ( event.phase == “began” ) then
bounce(self) --if this doesnt work, bounce(event.target) or bounce(spring)
–spring sound FX
springSound = audio.loadStream(“spring.mp3”)
backgroundMusicChannel = audio.play( springSound, { channel=2, loops=0 } )
–spring sound FX END
end
end

–Function to create string at needed x and y; add 1 to springCount per created string
–and add event listener to created string
– colision function
function create_string()
if springCount < 1 then --how many springs you can add
local spring = display.newImageRect( “Spring.png”,50,50)

physics.addBody( spring, “static”, { density=1, friction=0, bounce=1 } )
spring.x = 400
spring.y = 130
springCount = springCount + 1
spring:addEventListener(“touch”, move_spring)

– Adds collision listener to spring
spring.collision = onLocalCollision
spring:addEventListener( “collision”, spring)

elseif springCount == 1 then–how many springs you can add
print(“stop”) – there you can do anything you want, i just used print for debugging purposes
end
end

–With this function we touch the button and it changes its alpha and use create_string()
local function touch_button(event)
if event.phase == “began” then
print(“began”)
button.alpha = 0.5
elseif event.phase == “ended” then
print(“ended”)
button.alpha = 1
create_string()
end
end
– At last we adding event listener to button and watch magic happens:)
button:addEventListener(“touch”, touch_button)
—end new spring code
[/code] [import]uid: 72845 topic_id: 35475 reply_id: 143860[/import]

You need to add your spring to the camera:
[lua]
function create_string()
if springCount < 1 then --how many springs you can add
local spring = display.newImageRect( “Spring.png”,50,50)

physics.addBody( spring, “static”, { density=1, friction=0, bounce=1 } )
spring.x = 400
spring.y = 130
springCount = springCount + 1
spring:addEventListener(“touch”, move_spring)

– Adds collision listener to spring
spring.collision = onLocalCollision
spring:addEventListener( “collision”, spring)

camera:add(sprint, 1) – Add it to the same layer as the character

elseif springCount == 1 then–how many springs you can add
print(“stop”) – there you can do anything you want, i just used print for debugging purposes
end
end
[/lua]

Caleb [import]uid: 147322 topic_id: 35475 reply_id: 143887[/import]

Tried that. right now I have a character on a ledge, if I make the character walk off the ledge the spring I create falls with the character so they never collide. [import]uid: 72845 topic_id: 35475 reply_id: 143899[/import]

Are you getting any errors? Of any sort?

C [import]uid: 147322 topic_id: 35475 reply_id: 144003[/import]

I appreciate the responses. In regards to perspective I’m still a bit lost with the example.

--[[  
Perspective example main.lua  
   
Demonstrates parallax scrolling, damping, tracking objects, and setting the Perspective view focus.  
--]]  
local perspective=require("perspective") -- Include Perspective and create a view  
local camera=perspective.createView()  
camera.damping=20 -- Higher values make the camera slower and more "buttery"  
   
local referenceTable={} -- Table to hold all of the circles  
   
for i=1, 10 do  
 referenceTable[i]=display.newCircle(0, 0, math.random(40, 80))  
 referenceTable[i].x, referenceTable[i].y=math.random(1024), math.random(768)  
 referenceTable[i]:setFillColor(0, 0, 0, 0)  
 camera:add(referenceTable[i], 1, false) -- Add it to the camera  
 referenceTable[i].strokeWidth=6  
 referenceTable[i]:setStrokeColor(math.random(255), math.random(255), math.random(255))  
end  
   
local screenRect=display.newRect(0, 0, display.contentWidth, display.contentHeight) -- Make a bounding rectangle so you can see the screen dimensions  
screenRect:setFillColor(0, 0, 0, 0)  
screenRect.strokeWidth=4  
camera:add(screenRect, 1, false) -- Add the screenRect to the camera - in layer 1 because it has no parallaxRatio  
   
camera:setFocus(referenceTable[1]) -- Set the view's focus  
camera:track() -- Start tracking  
   
local function newTransition()  
 for i=1, #referenceTable do  
 transition.to(referenceTable[i], {x=math.random(display.contentWidth), y=math.random(display.contentHeight), time=1000}) -- Re-transition everything  
 end  
end  
   
local function setNewFocus() -- Get a random focus object  
 local obj=referenceTable[math.random(#referenceTable)]  
 camera:setFocus(obj)  
end  
   
newTransition() -- Initialize with a transition for each object  
timer.performWithDelay(5000, setNewFocus, 0) -- Add timers  
timer.performWithDelay(1000, newTransition, 0)  
   
for i=1, 8 do  
 camera:layer(i).parallaxRatio=math.random(1,10)/10 -- Get a random parallax ratio for each layer  
end  
   
for i=1, 60 do  
 local rect=display.newRect(0, 0, 20, 20) -- Populate the background with rectangles - normally you wouldn't want to have them all local without a reference, but I'm just doing this to show the parallax effect  
 rect.x, rect.y=math.random(display.contentWidth), math.random(display.contentHeight)  
 camera:add(rect, math.random(1,8), false) -- Add to a random layer  
end  

Instead of generating shapes at random how would you create for example 3 specific images that have the same parrallax effect? ex. grass, mountain, sky.

Also I noticed the rectangle that limits the movement of objects, can I use perspective to make a full screen unrestrained parrallax effect? Also how would you use a touch effect instead of the auto generated movement?

Thanks for your input
-FL [import]uid: 72845 topic_id: 35475 reply_id: 143345[/import]

What Perspective does is, instead of creating objects to parallax/track, it simply takes already made objects to parallax/track. So creating an object can be whatever you want; for three specific images, simply create three specific images.
Once you’ve created your images, you can add them to the camera and they will move according to the camera’s internal movement. Objects do not have to be created with a special format, or anything like that, they just have to be added to the camera. And parallax is achieved by layer, not by object. So here’s an example, assuming that you already loaded Perspective and created a camera view:
[lua]
local obj1=display.newImage(“MyImage.png”)
camera:add(obj1, 1)

local obj2=display.newImage(“MyImage2.png”)
camera:add(obj2, 2)
[/lua]
Now both objects will be included in the camera’s movement/tracking. Notice the second parameter for the :add() function. That’s the layer they will be included in. Objects in layer 1 will appear like an overlay over objects in layer 2, layer 2 is an overlay over layer 3, etc.
Once you’ve added objects, set the camera’s focus. The focus is the object that the camera tracks to follow - think Mario in a Mario-style game, and how he’s always visible, while the terrain moves.
[lua]
camera:setFocus(obj1)
[/lua]
To keep the focus within bounds (like you said about the rectangle) simply use the :setBounds() function, complete documentation is on the code page. If you don’t want bounds, set “false” as the first parameter (without quotes).
If you have the objects inside of the camera and the focus set (and bounds set, if you want them), you can start the camera moving. Simply use the :track() command, and it automatically keeps track of moving the world according to the position of the focus.
[lua]
camera:track()
[/lua]
Now all of that is taken care of, and all you need to do is move your character. The camera will follow it automatically.

Important: Make sure you insert all of the objects that will be moving with the camera into the camera - and physics doesn’t work well with parallax.

Caleb [import]uid: 147322 topic_id: 35475 reply_id: 143364[/import]

(What I mean by “physics doesn’t work well with parallax” was that things your player collides with should be in the same layer as the player) [import]uid: 147322 topic_id: 35475 reply_id: 143365[/import]

I understand what you’re saying about the layers, I’m just still a little confused about coding it to work.

I have

local perspective=require("perspective")  
local camera=perspective.createView()  
  
camera.x, camera.y=-200, -200  
  
local obj1=display.newImage("grass.png")  
camera:add(obj1, 1)  
   
local obj2=display.newImage("mountain.png")  
camera:add(obj2, 2)  
  
local obj3=display.newImage("sky.png")  
camera:add(obj3, 3)  
camera:setFocus(obj1)  
camera:setFocus(obj2)  
camera:setFocus(obj3)  
camera.offsetX, camera.offsetY=250, 150  
  
camera:setBounds(false)  
camera:track()  
obj1.x=event.x-camera.scrollX  
obj1:addEventListener("touch", touch\_obj1)  

but this definitely isn’t right : / [import]uid: 72845 topic_id: 35475 reply_id: 143370[/import]

Here, I’ll rewrite it for you, with comments:
[lua]
local perspective=require(“perspective”)
local camera=perspective.createView() – Include and create camera

–camera.x, camera.y=-200, -200 – This is the offset of the camera

local player=create_your_player_however_you_do_it()
camera:add(player, 1) – He’s in the front - layer 1 never has parallax

local grass=display.newImage(“grass.png”)
camera:add(grass, 1) – Add the grass in layer 1, with the player, because we want it to move the same as the player

local mountain=display.newImage(“mountain.png”)
camera:add(mountain, 7) – You can add this is layer 7, it’s a background object, so when we add parallax ability we’ll make it move less

local sky=display.newImage(“sky.png”)
camera:add(sky, 8) – And the same with this, although we’ll set layer 8’s parallax to barely moving

–camera.offsetX, camera.offsetY=250, 150 – This isn’t supported any more, see comment above

–THIS IS THE PARALLAX IMPLEMENTATION
camera:layer(7).parallaxRatio=0.5 – The layer with the mountain in it moves 0.5 times the player’s movement
camera:layer(8).parallaxRatio=0.2 – The layer with the sky in it moves 0.2 times the player’s movement

camera:setBounds(false) – No bounds
camera:track() – Start tracking the player

–Not sure what that last part was for
[/lua]
It’s important to note that Perspective does not restrict you on parallax or object creation - if you want, you can make layer 2 move less than layer 8, which moves more than layer 4 - and the objects are simply objects.

Caleb [import]uid: 147322 topic_id: 35475 reply_id: 143373[/import]

Here’s what I’ve got so far:

  
  
local perspective=require("perspective")  
local camera=perspective.createView() -- Include and create camera  
  
local physics = require("physics")  
physics.start()  
physics.setGravity(0,16)  
   
\_W = display.contentWidth; -- Get the width of the screen  
\_H = display.contentHeight; -- Get the height of the screen  
motionx = 0; -- Variable used to move character along x axis  
speed = 5.5; -- Set Walking Speed  
playerInAir = true; -- Set a boolean of whether our guy is in the air or not  
   
   
   
--camera.x, camera.y=200, 200 -- This is the offset of the camera  
  
local grass = display.newImage("grass.png")  
physics.addBody(grass, "static", {density=3,friction=3,bounce=0})  
grass.x = 130; grass.y = 460  
grass.myName = "grass"  
camera:add(grass, 1) -- Add the grass in layer 1, with the player, because we want it to move the same as the player  
   
local mountain = display.newImage("mountain.png")  
camera:add(mountain, 7) -- You can add this is layer 7, it's a background object, so when we add parallax ability we'll make it move less  
   
local sky = display.newImage("sky.png")  
camera:add(sky, 8) -- And the same with this, although we'll set layer 8's parallax to barely moving  
   
local guy = display.newImage( "guy.png" )  
 physics.addBody( guy, "dynamic", { friction=0.1, bounce=0.2 } )   
 guy.x = 1; guy.y = 50;  
 guy.myName = "guy"  
 guy.isFixedRotation = true  
 guy.isAlive = yes  
camera:add(guy, 1) -- He's in the front - layer 1 never has parallax  
   
  
   
   
   
   
   
   
local left = display.newImage ("btn\_arrow.png")  
 left.x = 45; left.y = 430;  
 left.rotation = 180;  
 camera:add(left, 1)  
  
local right = display.newImage ("btn\_arrow.png")  
 right.x = 180; right.y = 432;  
 camera:add(right, 1)  
  
local up = display.newImage ("btn\_arrow.png")  
 up.x = 740; up.y = 430;  
 up.rotation = 270;  
 camera:add(right, 1)  
  
  
  
  
  
-- Add Game Functionality  
  
-- Stop character movement when no arrow is pushed  
local function stop (event)  
 if event.phase =="ended" then  
 motionx = 0;  
 end   
end  
Runtime:addEventListener("touch", stop )  
  
-- Move character  
local function moveguy (event)  
 guy.x = guy.x + motionx;   
end  
Runtime:addEventListener("enterFrame", moveguy)  
  
-- When left arrow is touched, move character left  
function left:touch()  
 motionx = -speed;  
end  
left:addEventListener("touch",left)  
  
-- When right arrow is touched, move character right  
function right:touch()  
 motionx = speed;  
end  
right:addEventListener("touch",right)  
  
-- Make character jump  
function up:touch(event)  
 if(event.phase == "began" and playerInAir == false) then  
 playerInAir = true  
 guy:setLinearVelocity( 0, -200 )  
 end  
end  
up:addEventListener("touch",up)  
  
-- Detect whether the player is in the air or not  
function onCollision( event )  
 -- If guy is touching grass, allow jump  
 if(event.object1.myName == "grass" and event.object2.myName == "guy") then  
 playerInAir = false;  
 end   
end  
Runtime:addEventListener( "collision", onCollision )  
  
  
--THIS IS THE PARALLAX IMPLEMENTATION  
camera:layer(7).parallaxRatio=0.5 -- The layer with the mountain in it moves 0.5 times the player's movement  
camera:layer(8).parallaxRatio=0.2 -- The layer with the sky in it moves 0.2 times the player's movement  
   
camera:setBounds(false) -- No bounds  
camera:track() -- Start tracking the player  
   

My character moves and is in front of my other layers but the camera doesn’t follow him. Not sure why.

Thanks again for the help.
[import]uid: 72845 topic_id: 35475 reply_id: 143386[/import]

I think this should do it - at the end of your code, right before you call camera:track(), do a [lua]camera:setFocus(guy)[/lua]. That’ll tell the camera to use that player as the tracking object.

Caleb [import]uid: 147322 topic_id: 35475 reply_id: 143467[/import]

You sir are amazing. Thank you! [import]uid: 72845 topic_id: 35475 reply_id: 143479[/import]

No problem :slight_smile:

C [import]uid: 147322 topic_id: 35475 reply_id: 143484[/import]

1 quick question, is it possible to designate a set background without having to add camera?

Again thanks you rock! [import]uid: 72845 topic_id: 35475 reply_id: 143486[/import]