Placing one object in front of another in Corona SDK

I am building a platform jumper, and when the ball passes through the platform, I would like it to appear in front, not behind, the platform.  I’ve tried putting both objects into a new display group in the proper order and sending the ball to the front using toFront(), but I just can’t get it to work.  Any thoughts?

local ball = display.newCircle( 100, 100, 30 ) ball.id = "ball" ball.x, ball.y = 160, 350 ball.rotation = 15 local gradient = {     type="gradient",     color1={ 1, 4, 7 }, color2={ .1, 1, 1.5}, direction="down" } ball:setFillColor( gradient ) -- add physics to the ball physics.addBody( ball, "dynamic", { density=1.0,                friction=0.9, bounce=0 } ) -- create a platform w/ physics local bottom = display.newRect( 0, 0, 320, 100 ) bottom.anchorX = 0 bottom.anchorY = 1 bottom.x, bottom.y = 0, display.contentHeight physics.addBody( bottom, "static", { friction=0.3 } ) -- put plat in middle local platform = display.newRect( 0, 0, screenW-100, screenH-450 ) platform.x, platform.y = 160, 200 platform.collType = "passthru" physics.addBody( platform, "static", { bounce=0.0, friction=0.3 } ) -- place ball in front local group = display.newGroup( ) group:insert( ball ) group:insert( platform ) ball:toFront( )

** UPDATE: ADDED PHYSICS CODE TO EXAMPLE **

You’re probably doing something to change the order elsewhere in your code.  

Note: In your code you’ve got all the physics bodies as NON-sensors.  You need at least one to be a sensor otherwise they will not be allowed to occupy the same screen space.  Physics will push them apart.

If I’m reading your code right, it looks like you’re trying to make platforms like in this tutorial: http://coronalabs.com/blog/2013/02/19/more-physics-tricks-explained/

If so, you better go back and compare what you’ve done to the tutorial. You may have misunderstood this line

platform.collType = "passthru"

‘collType’ is not a physics (control) field.  It is a flag used by the tutorial code.  

‘isSensor’ is a control field for physics objects.  You can interpret it as ‘do not push’ or ‘do not simulate physical response’.

Finally, I’m sure the layering code is not the problem because, this (shorter) example below works fine in Corona 2014.2511

physics.start() physics.setGravity( 0,0 ) local cx = display.contentCenterX local cy = display.contentCenterY local group = display.newGroup() local ball1 = display.newCircle( group, cx-50, cy, 30 ) physics.addBody( ball1, "dynamic" ) ball1.isSensor = true ball1:setFillColor(1,0,0) local ball2 = display.newCircle( group, cx+50, cy, 30 ) physics.addBody( ball2, "dynamic" ) ball2.isSensor = true ball2:setFillColor(0,1,0) local rect = display.newRect( group, cx, cy, 100, 100 ) physics.addBody( rect, "dynamic" ) rect:setFillColor(0,0,1) ball1:toFront( )

Image2.png

Remember to always tell folks the version (release number)  of Corona you’re using when you need help.  Sometimes issues only occur with a specific release.  Regardless it helps folks reproduce the issue.

This is the version I am using: Version 2014.2393 (2014.8.5)

Here is the entirety of my code for this.  I don’t really see any other place where I am altering the positioning.

Also, I don’t think I quite understand what you mean by this:

 

If so, you better go back and compare what you’ve done to the tutorial. You may have misunderstood this line

platform.collType = “passthru”

‘collType’ is not a physics (control) field.  It is a flag used by the tutorial code.  

 

‘isSensor’ is a control field for physics objects.  You can interpret it as ‘do not push’ or ‘do not simulate physical response’.

-- forward declarations and other locals local screenW, screenH, halfW = display.contentWidth, display.contentHeight, display.contentWidth\*0.5 function scene:create( event ) local sceneGroup = self.view -- create a grey rectangle as the backdrop local background = display.newRect( 0, 0, screenW, screenH ) background.anchorX = 0 background.anchorY = 0 background:setFillColor( .5 ) -- make ball local ball = display.newCircle( 100, 100, 30 ) ball.id = "ball" ball.x, ball.y = 160, 350 ball.rotation = 15 local gradient = {     type="gradient",     color1={ 1, 4, 7 }, color2={ .1, 1, 1.5}, direction="down" } ball:setFillColor( gradient ) -- add physics to the ball physics.addBody( ball, "dynamic", { density=1.0,                friction=0.9, bounce=0 } ) -- create a platform w/ physics local bottom = display.newRect( 0, 0, 320, 100 ) bottom.anchorX = 0 bottom.anchorY = 1 bottom.x, bottom.y = 0, display.contentHeight physics.addBody( bottom, "static", { friction=0.3 } ) -- put plat in middle local platform = display.newRect( 0, 0, screenW-100, screenH-450 ) platform.x, platform.y = 160, 200 platform.collType = "passthru" physics.addBody( platform, "static", { bounce=0.0, friction=0.3 } ) -- place ball in front local group = display.newGroup( ) group:insert( ball ) group:insert( platform ) ball:toFront( ) ----------------------------- function ball:preCollision( event )    local plat = event.other    if plat.myName == "platform" then        -- Let ball pass through plat 1        event.contact.isEnabled = false        print( "preCollision", plat.myName )    end end ball:addEventListener( "preCollision" ) function ball:postCollision( event )    print( "Remove listeners")    self:removeEventListener( "preCollision" )    self:removeEventListener( "postCollision" ) end ball:addEventListener( "postCollision" ) ----------------------------- function ball:touch( event )    if event.phase == "began" then        print( "Touch event began on: " .. self.id )        ball:setLinearVelocity( 0, -200 )        print ("linear velocity set")    end    return true end ball:addEventListener( "touch", ball ) ----------------------------- function background:touch( event )    if event.phase == "began" then        print( "Touch event began on:bg " )        ball:setLinearVelocity( 0, -200 )        print ("linear velocity set")    end    return true end background:addEventListener( "touch", background ) ------------ function ball:preCollision( event ) if ( event.other.collType == "passthru" ) then local charBase = self.y+20 local platTop = event.other.y-32 if ( charBase \> platTop+8 ) then event.contact.isEnabled = false self.isSensor = true ; self.setAsSensor = true end end end function ball:collision( event ) local vx,vy = self:getLinearVelocity() if ( event.phase == "began" ) then local collType = event.other.collType if ( vy \>= 0 and self.inJump == true ) then self.inJump = false end if ( collType == "enemy" ) then self.inJump = true end self:applyLinearImpulse( vx\*0.0001, nil, self.x, self.y ) if ( self.setAsSensor == true ) then if ( collType == "solidV" ) then self:setLinearVelocity( -vx,vy ) elseif ( collType == "solidH" ) then self:setLinearVelocity( vx,-vy\*0.5 ) elseif ( collType == "enemy" ) then self:setLinearVelocity( -vx,-vy ) end end elseif ( event.phase == "ended" ) then self.isSensor = false ; self.setAsSensor = false end end ball:addEventListener( "preCollision" ) ball:addEventListener( "collision" ) ------------ -- all display objects must be inserted into group sceneGroup:insert( background ) sceneGroup:insert( ball ) sceneGroup:insert( bottom ) sceneGroup:insert( platform ) end

^ last line above inserts platform into group after background, ball, bottom ( in that order)

T.

** UPDATE: ADDED PHYSICS CODE TO EXAMPLE **

You’re probably doing something to change the order elsewhere in your code.  

Note: In your code you’ve got all the physics bodies as NON-sensors.  You need at least one to be a sensor otherwise they will not be allowed to occupy the same screen space.  Physics will push them apart.

If I’m reading your code right, it looks like you’re trying to make platforms like in this tutorial: http://coronalabs.com/blog/2013/02/19/more-physics-tricks-explained/

If so, you better go back and compare what you’ve done to the tutorial. You may have misunderstood this line

platform.collType = "passthru"

‘collType’ is not a physics (control) field.  It is a flag used by the tutorial code.  

‘isSensor’ is a control field for physics objects.  You can interpret it as ‘do not push’ or ‘do not simulate physical response’.

Finally, I’m sure the layering code is not the problem because, this (shorter) example below works fine in Corona 2014.2511

physics.start() physics.setGravity( 0,0 ) local cx = display.contentCenterX local cy = display.contentCenterY local group = display.newGroup() local ball1 = display.newCircle( group, cx-50, cy, 30 ) physics.addBody( ball1, "dynamic" ) ball1.isSensor = true ball1:setFillColor(1,0,0) local ball2 = display.newCircle( group, cx+50, cy, 30 ) physics.addBody( ball2, "dynamic" ) ball2.isSensor = true ball2:setFillColor(0,1,0) local rect = display.newRect( group, cx, cy, 100, 100 ) physics.addBody( rect, "dynamic" ) rect:setFillColor(0,0,1) ball1:toFront( )

Image2.png

Remember to always tell folks the version (release number)  of Corona you’re using when you need help.  Sometimes issues only occur with a specific release.  Regardless it helps folks reproduce the issue.

This is the version I am using: Version 2014.2393 (2014.8.5)

Here is the entirety of my code for this.  I don’t really see any other place where I am altering the positioning.

Also, I don’t think I quite understand what you mean by this:

 

If so, you better go back and compare what you’ve done to the tutorial. You may have misunderstood this line

platform.collType = “passthru”

‘collType’ is not a physics (control) field.  It is a flag used by the tutorial code.  

 

‘isSensor’ is a control field for physics objects.  You can interpret it as ‘do not push’ or ‘do not simulate physical response’.

-- forward declarations and other locals local screenW, screenH, halfW = display.contentWidth, display.contentHeight, display.contentWidth\*0.5 function scene:create( event ) local sceneGroup = self.view -- create a grey rectangle as the backdrop local background = display.newRect( 0, 0, screenW, screenH ) background.anchorX = 0 background.anchorY = 0 background:setFillColor( .5 ) -- make ball local ball = display.newCircle( 100, 100, 30 ) ball.id = "ball" ball.x, ball.y = 160, 350 ball.rotation = 15 local gradient = {     type="gradient",     color1={ 1, 4, 7 }, color2={ .1, 1, 1.5}, direction="down" } ball:setFillColor( gradient ) -- add physics to the ball physics.addBody( ball, "dynamic", { density=1.0,                friction=0.9, bounce=0 } ) -- create a platform w/ physics local bottom = display.newRect( 0, 0, 320, 100 ) bottom.anchorX = 0 bottom.anchorY = 1 bottom.x, bottom.y = 0, display.contentHeight physics.addBody( bottom, "static", { friction=0.3 } ) -- put plat in middle local platform = display.newRect( 0, 0, screenW-100, screenH-450 ) platform.x, platform.y = 160, 200 platform.collType = "passthru" physics.addBody( platform, "static", { bounce=0.0, friction=0.3 } ) -- place ball in front local group = display.newGroup( ) group:insert( ball ) group:insert( platform ) ball:toFront( ) ----------------------------- function ball:preCollision( event )    local plat = event.other    if plat.myName == "platform" then        -- Let ball pass through plat 1        event.contact.isEnabled = false        print( "preCollision", plat.myName )    end end ball:addEventListener( "preCollision" ) function ball:postCollision( event )    print( "Remove listeners")    self:removeEventListener( "preCollision" )    self:removeEventListener( "postCollision" ) end ball:addEventListener( "postCollision" ) ----------------------------- function ball:touch( event )    if event.phase == "began" then        print( "Touch event began on: " .. self.id )        ball:setLinearVelocity( 0, -200 )        print ("linear velocity set")    end    return true end ball:addEventListener( "touch", ball ) ----------------------------- function background:touch( event )    if event.phase == "began" then        print( "Touch event began on:bg " )        ball:setLinearVelocity( 0, -200 )        print ("linear velocity set")    end    return true end background:addEventListener( "touch", background ) ------------ function ball:preCollision( event ) if ( event.other.collType == "passthru" ) then local charBase = self.y+20 local platTop = event.other.y-32 if ( charBase \> platTop+8 ) then event.contact.isEnabled = false self.isSensor = true ; self.setAsSensor = true end end end function ball:collision( event ) local vx,vy = self:getLinearVelocity() if ( event.phase == "began" ) then local collType = event.other.collType if ( vy \>= 0 and self.inJump == true ) then self.inJump = false end if ( collType == "enemy" ) then self.inJump = true end self:applyLinearImpulse( vx\*0.0001, nil, self.x, self.y ) if ( self.setAsSensor == true ) then if ( collType == "solidV" ) then self:setLinearVelocity( -vx,vy ) elseif ( collType == "solidH" ) then self:setLinearVelocity( vx,-vy\*0.5 ) elseif ( collType == "enemy" ) then self:setLinearVelocity( -vx,-vy ) end end elseif ( event.phase == "ended" ) then self.isSensor = false ; self.setAsSensor = false end end ball:addEventListener( "preCollision" ) ball:addEventListener( "collision" ) ------------ -- all display objects must be inserted into group sceneGroup:insert( background ) sceneGroup:insert( ball ) sceneGroup:insert( bottom ) sceneGroup:insert( platform ) end

^ last line above inserts platform into group after background, ball, bottom ( in that order)

T.