How to have the "camera" follow target when it moves off-Screen?

Hi,

I have created a scrollable world, thanks to the post on parallax scrolling. but i’m trying to have the camera follow a moving object triggered by a “touch” EventListener. Unfortunately i have been unable to do so.

This is as far as i got with the code. Code examples would be very appreciated.

thanks

[code]

local physics = require(“physics”)
physics.start()

local worldLimits = { XMin=0 , YMin=0 , XMax=1200 , YMax=640 }

local p2_moveGroup = display.newGroup()

local p1_moveGroup = display.newGroup()

local p0_moveGroup = display.newGroup()

local p2 = p2_moveGroup
local p1 = p1_moveGroup
local p0 = p0_moveGroup

local adjustedXMax = display.contentWidth-worldLimits.XMax
local adjustedYMax = display.contentHeight-worldLimits.YMax

local baseline = 320

local background = display.newImageRect( p2_moveGroup, “background.png”, 1250, 770 )

local platform= display.newRect( p2_moveGroup, 0, baseline - 40, 100, 40 )
physics.addBody( platform, “static”, { friction=0.5 } )
platform:setFillColor( 88, 48, 32 )
platform.alpha = 1
platform.rotation = 0

local foreground = display.newImage( p1_moveGroup, “foreground.png” )
foreground:setReferencePoint( display.CenterLeftReferencePoint )
foreground.x = 0
foreground.y = 320 - 20

local ball = display.newCircle(p0_moveGroup, 60, 250, 20 ) – The Object the Camera needs to follow
physics.addBody( ball, { density=0.6, friction=0.6, bounce=0.3, radius=20} )
ball:setFillColor( 255, 110, 0 )
ball.alpha = 1
ball.myName = “ball”

local touchSensor = display.newRect( p0_moveGroup, 0, 0, worldLimits.XMax, worldLimits.YMax )
touchSensor:setFillColor(255,255,255,0)

local function clearTestDot(event)
event:removeSelf() ; event = nil
end

local function worldTouchPoint(event)
local adjustedX = event.x - p0.x
local adjustedY = event.y - p0.y
local touchpoint = display.newCircle( p0_moveGroup, adjustedX, adjustedY, 12 )
touchpoint:setFillColor(255,255,255,255)
transition.to( touchpoint, { time=1200, alpha=0.0, onComplete=clearTestDot } )
end

local function moveObject( event )
if ( event.phase == “began” ) then
display.getCurrentStage():setFocus( p0, event.id )
ball.angularVelocity = 500
ball:applyForce( 800, 850, ball.x, ball.y )
end
end
local function moveCamera( event )

– when touch first begins…
if ( event.phase == “began” ) then

– set core moveGroup to ‘focused’
display.getCurrentStage():setFocus( p0, event.id )

– set touch location to relative position (relative to moveGroup)
p0.x0 = event.x - p0.x
p0.y0 = event.y - p0.y

– when touch moves…
elseif ( event.phase == “moved” ) then

– set ‘predicted’ new X and Y positions for core moveGroup
p0.newX = event.x - p0.x0
p0.newY = event.y - p0.y0

– if new X position is within world limits, move it there!
if ( p0.newX <= worldLimits.XMin and p0.newX >= adjustedXMax ) then
p0.x = p0.newX ; p1.x = p0.x*0.4 ; p2.x = p0.x*0.2
– if not, lock to world limits to prevent further scrolling
elseif ( p0.newX > worldLimits.XMin ) then
p0.x = worldLimits.XMin ; p1.x = p0.x*0.4 ; p2.x = p0.x*0.2
elseif ( p0.newX < worldLimits.XMax ) then
p0.x = adjustedXMax ; p1.x = p0.x*0.4 ; p2.x = p0.x*0.2
end

– if new Y position is within world limits, move it there!
if ( p0.newY <= worldLimits.YMin and p0.newY >= adjustedYMax ) then
p0.y = p0.newY ; p1.y = p0.y*0.4 ; p2.y = p0.y*0.2
– if not, lock to world limits to prevent further scrolling
elseif ( p0.newY > worldLimits.YMin ) then
p0.y = worldLimits.YMin ; p1.y = p0.y*0.4 ; p2.y = p0.y*0.2
elseif ( p0.newY < worldLimits.YMax ) then
p0.y = adjustedYMax ; p1.y = p0.y*0.4 ; p2.y = p0.y*0.2
end

– when touch ends…
elseif ( event.phase == “ended” or event.phase == “cancelled” ) then
– un-focus core moveGroup
display.getCurrentStage():setFocus( p0, nil )
end

return true
end


ball:addEventListener( “touch”, moveObject )
p0:addEventListener( “touch”, moveCamera )
p0:addEventListener( “tap”, worldTouchPoint )
Runtime:addEventListener( “enterFrame”, moveCamera );

[import]uid: 10542 topic_id: 4258 reply_id: 304258[/import]

This could be slightly tricky, but I think the concept is this…

The parallax module works by “following” the user’s finger as it drags around the screen. In the case of a theoretical “camera” (since Corona doesn’t really utilize a camera concept, but a screen/content concept), you have to set the parallax module to follow an object, not a drag.

So, let’s say you have a ball moving to the right. As it moves, you would need to constantly track the difference between its X position and the “p0” parallax group’s X position (this would be done using a Runtime listener, similar to how a touch is tracked). With the difference value, you would then constantly “offset” the parallax group’s X position in relation to the ball’s X position, probably by calculating the difference, inverting it, and applying that value (relationally) to the p0 group’s X position.

Not sure if that makes sense… I can probably elaborate on this idea if necessary…

Brent
[import]uid: 9747 topic_id: 4258 reply_id: 13295[/import]

Hi Brent,

Thanks for the input. I have tried to do this but cant seem to make it work. I’m sure i’m doing something wrong.

I would appreciate some code to explain how this is done.

thanks [import]uid: 10542 topic_id: 4258 reply_id: 13300[/import]

Hi Swiftelf,
The “Egg Breaker” code example in the Corona sample code folder points out the basic concept. Look for it under:
“[Corona app folder] > SampleCode > Physics > EggBreaker”

See how the camera follows the boulder based on an “inverse” relation between the boulder.x and the game.x (game.x would basically be the same as “p0.x” in the parallax module).

-- Camera follows boulder automatically  
local function moveCamera()  
 if (boulder.x \> 80 and boulder.x \< 1100) then  
 game.x = -boulder.x + 80  
 end  
end  
  
Runtime:addEventListener( "enterFrame", moveCamera )  

This basic routine would then be expanded within the parallax module, so the background layers would move at a fractional rate, just like when the user drags the screen around.

I’ll probably tinker around with this later, but hopefully this gets you started in the right direction…
[import]uid: 9747 topic_id: 4258 reply_id: 13400[/import]

I’ll look into it right now

Thanks Brent [import]uid: 10542 topic_id: 4258 reply_id: 13404[/import]