Composer.remove scene not working

I am creating a game and when the user touches the ball they go into the next screen . My problem is that the first game scene isn’t getting cleared up properly . In the hide scene function on my first restart.lua file , this is the code :

function scene:hide(event) Runtime:removeEventListener("touch", touchScreen) composer.removeScene( "game" ) end

But as soon as I get into the restart screen the users time at the top goes away . 

If I put composer.removeScene( “game” ) in the game2.lua file , nothing happens . 

Can someone help me clear up the scenes properly ? I’ve look at the docs and nothing helped me.

First of all, please explain more. You said the user’s time goes away, where is the code for the user’s time?

Also, the remove scene code for the game scene would go in game.lua. 

Also, it seems an overlay would be pretty useful here: 

https://docs.coronalabs.com/api/library/composer/showOverlay.html

Please read.

Sorry I forgot the code . 

game.lua:

function scene:show(event) local sceneGroup = self.view composer.removeScene( "start" ) Ball:addEventListener( "tap", onBallTap ) end function scene:hide(event) local sceneGroup = self.view end function scene:destroy(event) end scene:addEventListener("create", scene) scene:addEventListener("show", scene) scene:addEventListener("hide", scene) scene:addEventListener("destroy", scene) return scene

restart.lua :

function scene:show(event) local phase = event.phase if ( phase == "will" ) then print("Phase started") elseif ( phase == "did" ) then print("phase showing objects") end Runtime:addEventListener("touch", touchScreen) end scene:addEventListener( "show" ) function scene:hide(event) Runtime:removeEventListener("touch", touchScreen) composer.removeScene( "game" ) end function scene:destroy(event) end scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) return scene

game2.lua:

function scene:show(event) local sceneGroup = self.view composer.removeScene( "restart" ) Ball:addEventListener( "tap", onBallTap ) end function scene:hide(event) Ball:removeEventListener( "tap", onBallTap ) end function scene:destroy(event) end scene:addEventListener("create", scene) scene:addEventListener("show", scene) scene:addEventListener("hide", scene) scene:addEventListener("destroy", scene) return scene

Hi

What is your onBallTap function?

One problem I see, and I know this has been explained before.  scene:show() and scene:hide() are called twice each time a scene changes. Each are called once with an event.phase == “will” before the scene shows or hides, and it’s called again with an event.phase == “did” after the scene shows or hides. 

The result 

function scene:hide(event) Runtime:removeEventListener("touch", touchScreen) --\<----- these 2 lines composer.removeScene( "game" ) --\<----- these 2 lines end

The lines I marked above are going to run twice because you are not testing to see which phase it is. Something like:

function scene:hide(event) if event.phase == "did" then Runtime:removeEventListener("touch", touchScreen) composer.removeScene( "game" ) end end

Somethings can’t really be run twice.

However I think your real problem is more timing related.  You are trying to remove the game scene from the restart scene ***AFTER*** the restart scene is over and it’s being told to hide.  Try moving the code to the scene:show() function instead:

function scene:show(event) --\<-------- notice this change. if event.phase == "did" then Runtime:removeEventListener("touch", touchScreen) --\<---- I'm not sure why you're adding a touch listener to the whole screen here composer.removeScene( "game" ) end end

Now look at the above code. I’m not sure why you’re adding a touch listener to the full screen to call a function called “touchScreen”. We don’t know what that function is doing and perhaps that would change my mind on how you should handle it.

Rob

game .lua onBallTap :

 function onBallTap( event ) timer.cancel(timerr) composer.gotoScene("restart",options) end

touch event function :

local function touchScreen( event ) if event.phase == "began" then composer.gotoScene( "game2", options ) end end

I’ll try what you said now .

This is what I have and the same thing is happening :

restart.lua:

function scene:show(event) local phase = event.phase if event.phase == "did" then Runtime:addEventListener("touch", touchScreen) end end function scene:hide(event) if event.phase == "did" then Runtime:removeEventListener("touch", touchScreen) composer.removeScene( "game" ) end end

Why not do this?

local function touchScreen( event ) if event.phase == "began" then composer.removeScene( "game" ) composer.gotoScene( "game2", options ) end end function scene:show(event) if event.phase == "did" then Runtime:addEventListener("touch", touchScreen) end end function scene:hide(event) if event.phase == "did" then Runtime:removeEventListener("touch", touchScreen) end end

I just tried the code you gave and the same thing is happening

Hello I’m still having problems with this

You have to learn to be much more expressive if you want to get additional help.  You have to communicate with us with more than “I’m still having problems with this”.  

Are you experiencing an error? If so, show us the output from the console log. Show us the line of code (and the code around it) where the error says it’s happening.

Is it just not working like you expect? Tell us what you expect and what you’re observing?

Tell us what you’ve done to try and solve this on your own? What have you tried?

Show us the current code. If you’ve made changes, we need to see how you made the changes.

Rob

I am creating a game and when the user touches the ball they go into the next screen . My problem is that the first game scene isn’t getting cleared up properly . In the hide scene function on my first restart.lua file .

As soon as I get into the restart screen the users time at the top goes away . 

If I put composer.removeScene( “game” ) in the game2.lua file , nothing happens . 

 

this is the code :

 

restart.lua:

-- requires local composer = require( "composer" ) local scene = composer.newScene() -- background local background function scene:create(event) local screenGroup = self.view local background = display.newImageRect("nextlevel.jpg",display.contentWidth,display.contentHeight) screenGroup:insert(background) end local options = { effect = "flip", time = 400 } local function touchScreen( event ) if event.phase == "began" then display.remove(timeLeft) composer.removeScene( "game" ) composer.gotoScene( "game2", options ) end end function scene:show(event) if event.phase == "did" then Runtime:addEventListener("touch", touchScreen) end end function scene:hide(event) if event.phase == "did" then Runtime:removeEventListener("touch", touchScreen) end end function scene:destroy(event) end scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) return scene

Hello ?

any help ?

I asked you several questions which for the most part you did not answer. What you did was restate the original problem and post some code that’s not your reset.lua scene.

It feels like you don’t understand the relationship of your scenes and what you need to do. And I suspect, you have us chasing a wrong problem.

You’re using Composer which is our scene manager. You have three scenes that seem to flow like this:

game.lua -> reset.lua -> game2.lua

I don’t know why you even have a reset.lua if you want to go game2.lua. You should be able to go directly to game2.lua and if you plan to go back to game.lua, then you can remove game.lua inside game2.lua.

Now based on the description, even a working reset.lua scene or removing the scene in game2.lua isn’t going to help. If you change scenes and you still see objects from the scene you left, it’s because you *did not*  add those objects to the game.lua scene.view group. If you are unable to hide the previous seen that’s the problem. Trying to remove the scene isn’t doing to do anything.

Rob

Have you looked through the Corona documentation? Many of the tutorials there are very useful, but you can’t copy and paste the code. You have to apply the knowledge and changes the code to fit yours. 

I would post them here, but Coronalabs.com is under maintenance.

Their are 10 game.lua scenes . And 10 restart.lua . The first scene is start.lua when the user touches the screen they go into game.lua . If they complete game.lua they go into restart.lua which makes then touch the screen to go into the next level (game2.lua) . And then that keeps going until they beat the game . If they run out of time , then they will go into another scene and restart the game over . Do I have to add the timer into the create scene to have it removed to ? I didn’t do this in other apps and they work perfectly fine . 

I’ll post my whole code to see if I can give you a better understanding of what’s happening .

game.lua:

-- requires local physics = require "physics" physics.start() local composer = require( "composer" ) local scene = composer.newScene() local background function scene:create(event) local screenGroup = self.view local randomImage = math.random(1,41) local background = display.newImageRect("images/background"..randomImage..".jpg",display.contentWidth,display.contentHeight) background.x = display.contentCenterX background.y = display.contentCenterY screenGroup:insert(background) CreateWalls(screenGroup,1) display.setDefault("fillColor", 0, 1, 1) -- create image of a ball Ball = display.newCircle(100, 100, 10) physics.addBody(Ball, "dynamic", {friction=2}) Ball:applyLinearImpulse(-.05, .05, 0, 0) screenGroup:insert(Ball) end local options = { effect = "fade", time = 400 } function SetDefaultAnchor( pos ) display.setDefault("anchorX", pos.x) display.setDefault("anchorY", pos.y) end function CreateWalls( ScreenGroup, BorderWidth ) -- make the math easier local OldAnchor = {x = display.getDefault(anchorX), y = display.getDefault(anchorY) } SetDefaultAnchor({x=0, y=0}) local Height = display.contentHeight -- + (2 \* BorderWidth) local Width = display.contentWidth -- + (2 \* BorderWidth) local leftWall = display.newRect( ScreenGroup, 0, 0, BorderWidth, Height) -- this is where the error is local rightWall = display.newRect( ScreenGroup, Width - BorderWidth, 0, BorderWidth, Height) local ceiling = display.newRect( ScreenGroup, 0, 0, Width, BorderWidth) local floor = display.newRect( ScreenGroup, 0, Height-BorderWidth, Width, BorderWidth) physics.addBody (leftWall, "static", {bounce = 0.7, friction = 2}) physics.addBody (rightWall, "static", {bounce = 0.0, friction = 2}) physics.addBody (ceiling, "static", {bounce = 0.8, friction = 2}) physics.addBody (floor, "static", {bounce = 0.0, friction = 2}) -- restore previous defaults SetDefaultAnchor(OldAnchor) end local timeLimit = 6 timeLeft = display.newText(timeLimit, 160, 20, native.systemFontBold, 24) timeLeft:setTextColor(255,0,0) function timerDown() timeLimit = timeLimit-1 timeLeft.text = timeLimit if(timeLimit==0)then display.remove(timeLeft) timer.cancel(timerr) composer.gotoScene("maxtime",options) end end timerr = timer.performWithDelay(1000,timerDown,timeLimit) function onBallTap( event ) timer.cancel(timerr) composer.gotoScene("restart",options) end function scene:show(event) local sceneGroup = self.view composer.removeScene( "start" ) Ball:addEventListener( "tap", onBallTap ) end function scene:hide(event) local sceneGroup = self.view end function scene:destroy(event) end scene:addEventListener("create", scene) scene:addEventListener("show", scene) scene:addEventListener("hide", scene) scene:addEventListener("destroy", scene) return scene

restart.lua:

-- requires local composer = require( "composer" ) local scene = composer.newScene() -- background local background function scene:create(event) local screenGroup = self.view local background = display.newImageRect("nextlevel.jpg",display.contentWidth,display.contentHeight) screenGroup:insert(background) end local options = { effect = "flip", time = 400 } local function touchScreen( event ) if event.phase == "began" then display.remove(timeLeft) composer.removeScene( "game" ) composer.gotoScene( "game2", options ) end end function scene:show(event) if event.phase == "did" then Runtime:addEventListener("touch", touchScreen) end end function scene:hide(event) if event.phase == "did" then Runtime:removeEventListener("touch", touchScreen) end end function scene:destroy(event) end scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) return scene

Firstly, is the gameplay in game.lua, game2.lua, game3.lua essentially the same, but maybe slightly harder or with additional elements?

And likewise the behaviour of the restart.lua, restart2.lua screens the same?

If so, this really isn’t an optimal way of doing things. Ideally you’d have one game.lua and one restart.lua, and keep track of the level number to determine how the level should play and what the restart screen displays.

Secondly, you specifically remove timeText in restart.lua. This timeLeft object is never added to scene.view in game.lua, so it won’t be cleared when calling removeScene.

I’d recommend creating objects either within scene:create or a function you can call from elsewhere. In your code you create some things within scene:create, some within CreateWalls(), but also some within the main listing. It’s easy to lose track of these ‘loose’ items, and forget to add them to the scene.view.

Edit: corrected timeText to timeLeft

  1. Yes . They are all the same it just gets harder as the levels go up .
  2. Yes all of the restart.lua scenes are basically the same .
  3. Where do I put the timer ? I thought it belonged to the function that’s why I didn’t put it in a scene function.

Also how do I do this ?

If so, this really isn’t an optimal way of doing things. Ideally you’d have one game.lua and one restart.lua, and keep track of the level number to determine how the level should play and what the restart screen displays.

There are various ways to persist data between scenes:

You can use the built in composer functionality to set (and get) variables.

https://docs.coronalabs.com/api/library/composer/setVariable.html

You can use a module:

[lua]

— globals.lua

local m = {}

 m.currentLevel = 1

return m

— game.lua

local glo = require(“globals”)

glo.currentLevel = glo.currentLevel + 1

— restart.lua

local glo = require(“globals”)

print (glo.currentLevel)  – this will be 2

[/lua]

Or you can save the values to disk:

https://forums.coronalabs.com/topic/62324-how-to-save-and-load-game-progress/