Question on RETRY a scene option.

Hi all,

So I have this weird finding when trying to make a RETRY option on a scene.

I have a scene named ‘scene1’ which has a retry button during a game pause, calls ‘retryLevel.lua’ which in turn calls back ‘scene1’.  

This is how I coded it initially (yes, using composer). 

-- in scene1.lua local function onPauseRetry() -- called when Retry button is pressed local thisScene = composer.getSceneName ("current") local options = { params = { level = thisScene } } composer.removeScene ( thisScene ) composer.gotoScene ("retryLevel", options ) end

--- in retryLevel.lua function scene:create( event ) local level = event.params.level composer:gotoScene (level, "fade", 50) end

It seems to work.   HOWEVER, on the second run of ‘scene1’, there are all sorts of weird errors and behaviour , especially in the game physics where everything seems to have doubled (eg. forces, tweening speed, density, etc.) which make me think that ‘scene1’ wasn’t totally cleaned up!   These properties seem to triple on the third retry, and so on until the scene just crashes!

So I revised ‘retry.lua’ to allow a small delay before calling back ‘scene1’ like so… 

-- in retryLevel.lua function scene:create( event ) local thisScene = composer.getSceneName ("current") local level = event.params.level composer:removeScene ( thisScene ) local function retry() composer:gotoScene (level, "fade", 50) end local t = timer.performWithDelay( 150, retry, 1 ) end

…and presto!!  I can retry ‘scene1’ as many times as I want with all those weirdness gone!   

So to my finding and question:   Corona needs some time to cleanup a scene before calling it back, Yes?   Secondly, is this the right way to do a ‘Retry’ option of a scene?  If there is anything better, would you guys recommend the method?

Thanks,

Santi

Hi @santiagoluib3

I have just finished creating an exit dialogue called from my main scene using composer:showOverlay().  Would this be a better solution for you when your game is paused?

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

Hi @simon491

That looks like a better method for handling a Pause/Resume dialogue (why I haven’t thought of using it is a mystery :smiley: ).  Thanks for reminding me of such a handy tool.

I can easily implement a Pause/Resume dialogue within the same scene.  My concern is more on restarting a scene from scratch (game over, retry same scene) , where it needs to be ‘clean’ and fresh, so my solution is to use an intermediary scene where I can totally destroy and cleanup the scene before calling it again.  It’s that behavior I discovered that if you call back the same scene instantaneously, it behaves weirdly (presuming some objects/physics haven’t totally cleared), so I had to put in some delay to make sure Corona has finished cleaning and destroying ‘scene1’ before the intermediary scene can call it again.  I found out 100-150ms works.

Do I make sense?  :) 

Thanks,

Santi

Oh by the way, that time param in the composer:gotoScene ()   (eg. composer:gotoScene (“scene1”, “fade”, 1000)  ) - that 1000 didn’t help at all.   It must be a delay BEFORE calling the gotoScene, hence i put the call in a timer delay.   That is at least my experience.

Hi Santi,

I’m not sure that I understand your specific scenario, but I call a parent function in the overlay hide scene

function scene:hide( event ) local sceneGroup = self.view local phase = event.phase local parent = event.parent -- Reference to the parent scene object if ( phase == "did" ) then -- Call the "resumeGame()" function in the parent scene parent:resumeMain() end end

Yes that is fine, I get the concept…  calling back the parent scene to resume.  

Now, what if aside from the Resume button, you have Retry button in your overlay scene to let the player restart the level? Do you have the code in your parent scene to handle this?  (eg… Play the scene again from start) ?

Cheers!

Santi 

Stop physics and timers when you leave a scene to avoid bugs.

https://forums.coronalabs.com/topic/69657-enterframe-proxy-stops-after-re-going-on-a-scene/

See also the tutorial for reloading scene : https://docs.coronalabs.com/guide/system/composer/index.html#reloading-scenes

And it’s a dot, not a collon for goToScene.

– in scene1.lua local function onPauseRetry() – called when Retry button is pressed local thisScene = composer.getSceneName (“current”) local options = { params = { level = thisScene } } composer.removeScene ( thisScene ) – THIS composer.gotoScene (“retryLevel”, options ) end

you can’t remove the current scene - so this call is failing, so you scene isn’t getting disposed of properly.  instead try calling removeHidden  (or removeScene explicitly on scene1) from your retry scene in response to show-did.

@davebollinger,

Apparently, I can (remove current scene).  I’m not sure if something breaks under the hood while doing that but I’ve been running it on my tests with no apparent problems at all.   Yes I tried using removeHidden on the right spot but the same problem described on the original post problem happens.  Same thing happens on explicitly calling removescene for scene1.  So the only “fix”? i found at the moment was to add that small delay before calling scene1 again on a Retry (refer to orig. post) and the problem is gone.

@yvandotet,

Yes, it should be dot not colon (typo error), thanks for bringing that up.

Santi   

You should never remove the scene you are in. Chaos could ensue. There is only one safe time to remove the scene you are in and that’s in the scene:hide() event’s “did” phase. At that point, your scene is fully off screen and then you can have it remove itself.  We’ve tested this and it works and probably should be the way of cleaning up a scene.

That said, I personally still prefer to remove the scene in the cut scene.

In your game scene, either in your code just before you call composer.gotoScene() to your cutscene, pause everything (physics, timers, transitions, audio (in particular with onComplete’s). If you don’t do this just before you call gotoScene() then you must do this in scene:hide()'s “will” phase. You don’t want anything left running.

Then in scene:hide()'s “did” phase, you can have the scene remove itself or wait until the cut scene’s fully on screen and then remove the game scene there. Make sure you provide the user some interactivity, like a “try again” button" and then go to your game scene and it should restart freshly.

Rob

Thanks a lot Rob, as well to the rest in this thread!   Really great help.

Now can finally put this to rest whilst in the past I used to put removeScene just about anywhere I thought was ok.  

Tried it and the game plays smoothly on my ‘Retry’ option as well as jumping from one scene to another.  

@Rob,

I am about to update my thread on my build timeouts issues, this time with a complete console log.  Unfortunately I am still having that issue.  Hopefully you guys can spot the reasons.  I need to come up with a playable prototype APK soon at CoronaDefold jam hopefully but not with this issue :frowning:

Santi

Hi @santiagoluib3

I have just finished creating an exit dialogue called from my main scene using composer:showOverlay().  Would this be a better solution for you when your game is paused?

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

Hi @simon491

That looks like a better method for handling a Pause/Resume dialogue (why I haven’t thought of using it is a mystery :smiley: ).  Thanks for reminding me of such a handy tool.

I can easily implement a Pause/Resume dialogue within the same scene.  My concern is more on restarting a scene from scratch (game over, retry same scene) , where it needs to be ‘clean’ and fresh, so my solution is to use an intermediary scene where I can totally destroy and cleanup the scene before calling it again.  It’s that behavior I discovered that if you call back the same scene instantaneously, it behaves weirdly (presuming some objects/physics haven’t totally cleared), so I had to put in some delay to make sure Corona has finished cleaning and destroying ‘scene1’ before the intermediary scene can call it again.  I found out 100-150ms works.

Do I make sense?  :) 

Thanks,

Santi

Oh by the way, that time param in the composer:gotoScene ()   (eg. composer:gotoScene (“scene1”, “fade”, 1000)  ) - that 1000 didn’t help at all.   It must be a delay BEFORE calling the gotoScene, hence i put the call in a timer delay.   That is at least my experience.

Hi Santi,

I’m not sure that I understand your specific scenario, but I call a parent function in the overlay hide scene

function scene:hide( event ) local sceneGroup = self.view local phase = event.phase local parent = event.parent -- Reference to the parent scene object if ( phase == "did" ) then -- Call the "resumeGame()" function in the parent scene parent:resumeMain() end end

Yes that is fine, I get the concept…  calling back the parent scene to resume.  

Now, what if aside from the Resume button, you have Retry button in your overlay scene to let the player restart the level? Do you have the code in your parent scene to handle this?  (eg… Play the scene again from start) ?

Cheers!

Santi 

Stop physics and timers when you leave a scene to avoid bugs.

https://forums.coronalabs.com/topic/69657-enterframe-proxy-stops-after-re-going-on-a-scene/

See also the tutorial for reloading scene : https://docs.coronalabs.com/guide/system/composer/index.html#reloading-scenes

And it’s a dot, not a collon for goToScene.

– in scene1.lua local function onPauseRetry() – called when Retry button is pressed local thisScene = composer.getSceneName (“current”) local options = { params = { level = thisScene } } composer.removeScene ( thisScene ) – THIS composer.gotoScene (“retryLevel”, options ) end

you can’t remove the current scene - so this call is failing, so you scene isn’t getting disposed of properly.  instead try calling removeHidden  (or removeScene explicitly on scene1) from your retry scene in response to show-did.

@davebollinger,

Apparently, I can (remove current scene).  I’m not sure if something breaks under the hood while doing that but I’ve been running it on my tests with no apparent problems at all.   Yes I tried using removeHidden on the right spot but the same problem described on the original post problem happens.  Same thing happens on explicitly calling removescene for scene1.  So the only “fix”? i found at the moment was to add that small delay before calling scene1 again on a Retry (refer to orig. post) and the problem is gone.

@yvandotet,

Yes, it should be dot not colon (typo error), thanks for bringing that up.

Santi   

You should never remove the scene you are in. Chaos could ensue. There is only one safe time to remove the scene you are in and that’s in the scene:hide() event’s “did” phase. At that point, your scene is fully off screen and then you can have it remove itself.  We’ve tested this and it works and probably should be the way of cleaning up a scene.

That said, I personally still prefer to remove the scene in the cut scene.

In your game scene, either in your code just before you call composer.gotoScene() to your cutscene, pause everything (physics, timers, transitions, audio (in particular with onComplete’s). If you don’t do this just before you call gotoScene() then you must do this in scene:hide()'s “will” phase. You don’t want anything left running.

Then in scene:hide()'s “did” phase, you can have the scene remove itself or wait until the cut scene’s fully on screen and then remove the game scene there. Make sure you provide the user some interactivity, like a “try again” button" and then go to your game scene and it should restart freshly.

Rob