Composer.remove scene not working

https://docs.coronalabs.com/ is still available, it’s just the main website we are working on.

In addition to Nick’s spot on answer, in game.lua you never add “timeLeft” object to the scene either. This will hang around when you change scenes.

Also semantics are important when programming.  You don’t create a variable “NumberOfApples” to hold a display.newImageRect() object of a picture of a car. “restart.lua” implies that you are attempting to restart a level, not go to a new level. I tend to name that scene “nextlevel.lua” 

I’d also recommend you read up on scope within lua, as you seem to be declaring a lot of global variables and functions. There’s no need for timerr to be global just so you can access it from the tap listener. Declare local timerr at the top of your lua file, and then assign the timer to this at the appropriate time.

Once you have your currentLevel variable available within game.lua, you just use this to determine how hard your level is. That might be by adjusting the size or speed or the ball, the amount of time before game over etc.

Just as an example…

[lua]

local ballSpeed = 5 + (glo.currentLevel * 0.25)

local ballSize = 20 - (glo.currentLevel) 

local gameTime = 90 - (glo.currentLevel * 5)

[/lua]

or…

[lua]

local ballSpeeds = {5, 6, 8, 10, 15, 20, 30, 40, 60}

local ballSizes = {20, 19, 18, 15, 12, 10,8, 7, 6, 5}

local gameTimes = {90, 85, 75, 70, 60, 55, 48, 45, 42, 40}

local ballSpeed = ballSpeeds[glo.currentLevel]

local ballSize = ballSizes[glo.currentLevel]

local gameTime = gameTimes[glo.currentLevel]

[/lua]

I don’t know why but I just put it as restart . Do I have to change it ?

This seems a little complicated so I would like to do it the way I’m already doing it because I wouldn’t understand the way you suggested . 

You don’t have to change restart.lua to nextlevel.lua. That’s not a hard rule. As long as you know what you’re doing and what the purpose that scene serves, that’s really all that matters. However when asking for help, had we seen “nextscene.lua” it would have helped us understand the problem a bit better. So if you want to re-ask the question “Should I change it” then the answer becomes “I would recommend it”.

Rob

Ok I did.

Trust me, a little extra reading and work now to understand this will save you countless hours in the future. Imagine your game in the future has 20, 30, 40 levels, game.lua, game1.lua, game2.lua etc. What happens when you want to change something as to how the basic game works, or add some extra HUD text. You’d have to make this change in all 20, 30, 40 files.

Ok so are there any docs that will help me start ?

It’s not so much docs you need, as putting together a few basic coding principles that you’ll need to become a good developer.

  1. Have a variable for the currentLevel, that can be accessed throughout the app. I posted various ways of doing that.

  2. Adjust how your level behaves and is built depending on the value of currentLevel. So instead of hard-coding things like speed or size,  use variables to set these. I posted a couple of ways of doing that - if the level is 1 it might grab/calculate a value of 20 for speed, if the level is 2 it might grab/calculate a value of 25.

What things does Level 2 change? Is it just a shorter timer? Quicker ball? Smaller ball?

Imagine Sonic the Hedgehog. If they built that in Corona, they wouldn’t have greenhillzone.lua, marblezone.lua etc, all containing the same logic for controlling Sonic, moving platforms, collecting rings, displaying his number of lives etc. They’d have one Lua file for game logic, and then depending on the level Sonic is on import data about what tiles, objects and enemies should go where. If they want to make Sonic have a faster top speed, they just change one value in game.lua. 

What things does Level 2 change? Is it just a shorter timer? Quicker ball? Smaller ball?

The ball moves faster and the timer is a little bit longer .

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