Problem restarting a scene

I have an intermediate scene for when it’s “Game Ove” I can reload the first scene again:

gameScene:

gameOver = function (  ) -- gets called in a collision event      -- Code to remove eventListeners and do some cleaning.     composer.gotoScene( "gameOverScene" , {time=2000, effect="flip"} ) end

gameOveScene:

function scene:create( event )     local sceneGroup = self.view     composer.removeScene( "gameScene")     composer.gotoScene( "gameScene" , {time=1000, effect="flip"} ) end

The problem is that the scene does restart but the behaviour is all messed up. I do reset the values for stuff like (score) but the game doesn’t run as expected the second time, and the event for"gamOver" doesn’t execute the second time. Also, the transition effect doesn’t occur. 

Two things going on here:

One, the scene will not be completely reset because the module is still in memory. You are probably finding that objects which you thought would get cleared away are not, perhaps you haven’t seen that they’re not yet, but you will.

The second is that you can’t manipulate the physics objects locked during a collision event, so those will definitely still be around when you try to clean out the scene.

These are common problems and has been answered many times before - I’m pretty sure there’s blog posts about it, too.

The solution to the first is to go to an intermediate scene and perhaps force a removal of the original game scene. This is not what most developers want to do, but the alternatives are more complex. I recommend having an intermediate scene which looks like a black screen and forcing a clean of the game scene.

The second problem is easier to solve. Basically, when a collision occurs you will find that the engine locks the physics body to prevent changes until after the collision. What you need to do is fire a timer for the shortest possible time (recommended: 1 millisecond) and perform the change there.

I’m sure others have more elegant solutions, so I hope someone else will respond, too.

@horacebury pretty much summed up the problem. But I’ll argue that having a cut scene is important to have. If your game is physical (lots of touches, taps and swipes or lots of key presses, controller button presses), a player’s hand can get tired. Cut scenes provide a logical break in the game and give the player a chance to refocus themselves, work their hand cramps out and reset their focus.  

But there are times where it’s not practical. In the game I’m building now, I want to give a “Restart” button on my Pause screen, which is an overlay on the game scene. It’s not practical for me to use a cut-scene at this point, so I’m going to have to structure my code in a way that I can remove all the objects, re-position the background, reset all of my player’s stats, score, health, etc. It’s going to be a lot of work.

One way that will help is to have your code to start a game, reset a game etc. in their own functions. Then when Composer calls scene:show() during the “did” phase, you call the start game function instead of having that code in scene:show() the reason for this is so that you can call that function without having to have scene changes. Blowing away the scene using composer.removeScene() is by far much easier to do. Since every game is different, it would be nearly impossible to discuss how to reset your scene any in any more detail.

Rob

As I understand, If I do this in an intermediate scene:

    composer.removeScene( "gameScene")     composer.gotoScene( "gameScene" , {time=1000, effect="flip"} )

the original scene “gameScene” should get removed from the memory and then restart again as if the app itself was being freshly opened, am I wrong to assume that? because that’s what I’m doing right now+ doing some cleaning in “gameScene” before moving on to the intermediate one. 

Doing those two lines in an intermediate scene should work.

Rob

Ok, I’m having some trouble understanding how this process works. What does exactly:

    composer.removeScene( "gameScene")

do? It doesn’t remove display objects or stop listeners, I have to do that and reset everything manually. If there is some sort of basic tutorial for the best way to restart a scene  I would appreciate it. 

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

If you read the above docs page you’ll see that removeScene() removes the scene from memory. There is an option to keep the scene object in memory, but I would personally have everything removed - this includes the scene object and the display group ‘view’ object.

As noted, a destroy event is dispatched to the scene first, so it is in the listener function for this event where you should clean up everything related to the whole scene - event listeners and everything. Anything which attaches an event listener to a display group or the Runtime object will remain in memory even if it’s display object is removed, so you need to clean everything. The one caveat to that is that anything which listens to itself will be removed when itself is removed, because of the circular reference no longer existing. But anything listening to things like Runtime will cause problems.

Two things going on here:

One, the scene will not be completely reset because the module is still in memory. You are probably finding that objects which you thought would get cleared away are not, perhaps you haven’t seen that they’re not yet, but you will.

The second is that you can’t manipulate the physics objects locked during a collision event, so those will definitely still be around when you try to clean out the scene.

These are common problems and has been answered many times before - I’m pretty sure there’s blog posts about it, too.

The solution to the first is to go to an intermediate scene and perhaps force a removal of the original game scene. This is not what most developers want to do, but the alternatives are more complex. I recommend having an intermediate scene which looks like a black screen and forcing a clean of the game scene.

The second problem is easier to solve. Basically, when a collision occurs you will find that the engine locks the physics body to prevent changes until after the collision. What you need to do is fire a timer for the shortest possible time (recommended: 1 millisecond) and perform the change there.

I’m sure others have more elegant solutions, so I hope someone else will respond, too.

@horacebury pretty much summed up the problem. But I’ll argue that having a cut scene is important to have. If your game is physical (lots of touches, taps and swipes or lots of key presses, controller button presses), a player’s hand can get tired. Cut scenes provide a logical break in the game and give the player a chance to refocus themselves, work their hand cramps out and reset their focus.  

But there are times where it’s not practical. In the game I’m building now, I want to give a “Restart” button on my Pause screen, which is an overlay on the game scene. It’s not practical for me to use a cut-scene at this point, so I’m going to have to structure my code in a way that I can remove all the objects, re-position the background, reset all of my player’s stats, score, health, etc. It’s going to be a lot of work.

One way that will help is to have your code to start a game, reset a game etc. in their own functions. Then when Composer calls scene:show() during the “did” phase, you call the start game function instead of having that code in scene:show() the reason for this is so that you can call that function without having to have scene changes. Blowing away the scene using composer.removeScene() is by far much easier to do. Since every game is different, it would be nearly impossible to discuss how to reset your scene any in any more detail.

Rob

As I understand, If I do this in an intermediate scene:

    composer.removeScene( "gameScene")     composer.gotoScene( "gameScene" , {time=1000, effect="flip"} )

the original scene “gameScene” should get removed from the memory and then restart again as if the app itself was being freshly opened, am I wrong to assume that? because that’s what I’m doing right now+ doing some cleaning in “gameScene” before moving on to the intermediate one. 

Doing those two lines in an intermediate scene should work.

Rob

Ok, I’m having some trouble understanding how this process works. What does exactly:

    composer.removeScene( "gameScene")

do? It doesn’t remove display objects or stop listeners, I have to do that and reset everything manually. If there is some sort of basic tutorial for the best way to restart a scene  I would appreciate it. 

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

If you read the above docs page you’ll see that removeScene() removes the scene from memory. There is an option to keep the scene object in memory, but I would personally have everything removed - this includes the scene object and the display group ‘view’ object.

As noted, a destroy event is dispatched to the scene first, so it is in the listener function for this event where you should clean up everything related to the whole scene - event listeners and everything. Anything which attaches an event listener to a display group or the Runtime object will remain in memory even if it’s display object is removed, so you need to clean everything. The one caveat to that is that anything which listens to itself will be removed when itself is removed, because of the circular reference no longer existing. But anything listening to things like Runtime will cause problems.