Unable to reset scene

From my menu scene i go to game scene. At the end of the game I go back to menu and then back to game however, game never resets.

Ive tried to make sure I put everything into the scenegroup. Ive tried making sure all listeners are removed, all timers are stopped, everything set to nil and yet still no luck.

Code below 

[lua]---------------------------------------------------------------------------------

– game.lua


local sceneName = …

local composer = require( “composer” )
local physics = require(“physics”)
physics.start();
physics.setGravity( 0, 0 )

– Load scene with same root filename as this file
local scene = composer.newScene( sceneName )


local bg
local donut
local fly1
local fly2
local fly3
local flies = {}
local stuckflies = {}
local blood = {}
local speed = 0.5
local math_random = math.random
local endflag = false
local myTimer

local function die(event)
local fly = event.target
blood[#blood + 1] = display.newImageRect (“images/blood.png”, 30, 31)
blood[#blood].x = fly.x
blood[#blood].y = fly.y

scene.view:insert(blood[#blood])

for k=#flies, 1, -1 do
if (flies[k] == fly) then
flies[k].isVisible = false;
flies[k]:removeEventListener( “tap”, die )
flies[k]:removeEventListener( “collision”, reachdonut )
flies[k]:removeSelf();
flies[k] = nil
table.remove(flies,k);

end
end
return blood[#blood]
end

local function reachdonut(self, event)

if (fly3) then
fly3:removeSelf()
fly3 = nil
elseif (fly2) then
fly2:removeSelf()
fly2 = nil
elseif (fly1) then
fly1:removeSelf()
fly1 = nil
endflag = true
end

stuckflies[#stuckflies + 1] = display.newImageRect (“images/fly.png”, 30, 32)
stuckflies[#stuckflies].x = self.x
stuckflies[#stuckflies].y = self.y
stuckflies[#stuckflies].rotation = self.rotation

scene.view:insert(stuckflies[#stuckflies])

for k=#flies, 1, -1 do
if (flies[k] == self) then
flies[k].isVisible = false;
flies[k]:removeEventListener( “tap”, die )
flies[k]:removeEventListener( “collision”, reachdonut )
flies[k]:removeSelf();
flies[k] = nil
table.remove(flies,k);

end
end

if (endflag == true) then

composer.gotoScene( “menu”)
end
return stuckflies[#stuckflies]
end

local function spawn()

local math_deg = math.deg --localize ‘math.deg’ for better performance
local math_atan2 = math.atan2 --localize ‘math.atan2’ for better performance

local function angleBetween( srcX, srcY, dstX, dstY )
local angle = ( math_deg( math_atan2( dstY-srcY, dstX-srcX ) )+90 ) --; return angle
if ( angle < 0 ) then angle = angle + 360 end ; return angle % 360
end

flies[#flies + 1] = display.newImageRect (“images/fly.png”, 30, 32)
local edge = math_random(1,4)

if (edge == 1) then
–top
flies[#flies].y = 0
flies[#flies].x = math_random(0, 480)
end
if (edge == 2) then
–bottom
flies[#flies].y = 320
flies[#flies].x = math_random(0, 480)
end
if (edge == 3) then
–left
flies[#flies].y = math_random(0, 320)
flies[#flies].x = 0
end
if (edge == 4) then
–right
flies[#flies].x = 480
flies[#flies].y = math_random(0, 320)
end

local ang = angleBetween( flies[#flies].x, flies[#flies].y, donut.x, donut.y )

flies[#flies].rotation = ang
physics.addBody( flies[#flies], “dynamic”, { density=1.0, friction=1.0, bounce=0, radius=10 } )

flyxdirection = donut.x - flies[#flies].x
flyydirection = donut.y - flies[#flies].y
flies[#flies]:setLinearVelocity( flyxdirection*speed, flyydirection*speed )
flies[#flies].collision = reachdonut

flies[#flies]:addEventListener( “collision” )
flies[#flies]:addEventListener( “tap”, die )

scene.view:insert(flies[#flies])
return flies[#flies]
end

function scene:create( event )
local sceneGroup = self.view

bg = display.newImageRect (“images/bg.png”, 570, 360)
bg.x =display.contentWidth*0.5
bg.y = display.contentHeight*0.5

donut = display.newImageRect (“images/donut.png”, 75, 75)
donut.x =display.contentWidth*0.5
donut.y = display.contentHeight*0.5

physics.addBody( donut, “static”, { density=1.0, friction=1.0, bounce=0, radius=25 } )

fly1 = display.newImageRect (“images/fly.png”, 32, 30)
fly1.x = 30
fly1.y = 25

fly2 = display.newImageRect (“images/fly.png”, 32, 30)
fly2.x = 70
fly2.y = 25

fly3 = display.newImageRect (“images/fly.png”, 32, 30)
fly3.x = 110
fly3.y = 25

–Insert into groups

sceneGroup:insert (bg)
sceneGroup:insert (donut)
sceneGroup:insert (fly1)
sceneGroup:insert (fly2)
sceneGroup:insert (fly3)

– Called when the scene’s view does not exist

– INSERT code here to initialize the scene
– e.g. add display objects to ‘sceneGroup’, add touch listeners, etc
end

function scene:show( event )
local sceneGroup = self.view
local phase = event.phase

if ( phase == “will” ) then
– Called when the scene is still off screen (but is about to come on screen).
elseif ( phase == “did” ) then
– Called when the scene is now on screen.
– Insert code here to make the scene come alive.
– Example: start timers, begin animation, play audio, etc.

myTimer = timer.performWithDelay(1000, spawn, 10)

end

end

function scene:hide( event )
local sceneGroup = self.view

end

function scene:destroy( event )
local sceneGroup = self.view

bg:removeSelf()
bg = nil
donut:removeSelf()
donut = nil

for k=#flies, 1, -1 do
flies[k].isVisible = false
flies[k]:removeEventListener( “tap”, die )
flies[k]:removeEventListener( “collision”, reachdonut )
flies[k]:removeSelf()
flies[k] = nil
table.remove(flies,k)
end
for k=#stuckflies, 1, -1 do
stuckflies[k].isVisible = false
stuckflies[k]:removeSelf()
stuckflies[k] = nil
table.remove(stuckflies,k)
end
for k=#blood, 1, -1 do
blood[k].isVisible = false
blood[k]:blood()
blood[k] = nil
table.remove(blood,k)
end
if myTimer ~= nil then
timer.cancel(myTimer)
myTimer = nil
end

– Called prior to the removal of scene’s “view” (sceneGroup)

– INSERT code here to cleanup the scene
– e.g. remove display objects, remove touch listeners, save state, etc
end


– Listener setup
scene:addEventListener( “create”, scene )
scene:addEventListener( “show”, scene )
scene:addEventListener( “hide”, scene )
scene:addEventListener( “destroy”, scene )


return scene
[/lua]

The code most of your code above scene create needs to go inside scene create.

Hi,

I’ve tried to move everything into the scene create function but still no luck

[lua]---------------------------------------------------------------------------------

– game.lua


local sceneName = …

local composer = require( “composer” )
local physics = require(“physics”)
physics.start();
physics.setGravity( 0, 0 )

– Load scene with same root filename as this file
local scene = composer.newScene( sceneName )


function scene:create( event )
local sceneGroup = self.view

local bg
local donut
local fly1
local fly2
local fly3
local flies = {}
local stuckflies = {}
local blood = {}
local speed = 0.5
local math_random = math.random
local endflag = false
local myTimer

bg = display.newImageRect (“images/bg.png”, 570, 360)
bg.x =display.contentWidth*0.5
bg.y = display.contentHeight*0.5

donut = display.newImageRect (“images/donut.png”, 75, 75)
donut.x =display.contentWidth*0.5
donut.y = display.contentHeight*0.5

physics.addBody( donut, “static”, { density=1.0, friction=1.0, bounce=0, radius=25 } )

fly1 = display.newImageRect (“images/fly.png”, 32, 30)
fly1.x = 30
fly1.y = 25

fly2 = display.newImageRect (“images/fly.png”, 32, 30)
fly2.x = 70
fly2.y = 25

fly3 = display.newImageRect (“images/fly.png”, 32, 30)
fly3.x = 110
fly3.y = 25

–Insert into groups

sceneGroup:insert (bg)
sceneGroup:insert (donut)
sceneGroup:insert (fly1)
sceneGroup:insert (fly2)
sceneGroup:insert (fly3)

local function die(event)
local fly = event.target
blood[#blood + 1] = display.newImageRect (“images/blood.png”, 30, 31)
blood[#blood].x = fly.x
blood[#blood].y = fly.y

sceneGroup:insert(blood[#blood])

for k=#flies, 1, -1 do
if (flies[k] == fly) then
flies[k].isVisible = false;
flies[k]:removeEventListener( “tap”, die )
flies[k]:removeEventListener( “collision”, reachdonut )
flies[k]:removeSelf();
flies[k] = nil
table.remove(flies,k);

end
end
return blood[#blood]
end

local function reachdonut(self, event)

if (fly3) then
fly3:removeSelf()
fly3 = nil
elseif (fly2) then
fly2:removeSelf()
fly2 = nil
elseif (fly1) then
fly1:removeSelf()
fly1 = nil
endflag = true
end

stuckflies[#stuckflies + 1] = display.newImageRect (“images/fly.png”, 30, 32)
stuckflies[#stuckflies].x = self.x
stuckflies[#stuckflies].y = self.y
stuckflies[#stuckflies].rotation = self.rotation

sceneGroup:insert(stuckflies[#stuckflies])

for k=#flies, 1, -1 do
if (flies[k] == self) then
flies[k].isVisible = false;
flies[k]:removeEventListener( “tap”, die )
flies[k]:removeEventListener( “collision”, reachdonut )
flies[k]:removeSelf();
flies[k] = nil
table.remove(flies,k);

end
end

if (endflag == true) then

composer.gotoScene( “gameover”)
end
return stuckflies[#stuckflies]
end

local function spawn()

local math_deg = math.deg --localize ‘math.deg’ for better performance
local math_atan2 = math.atan2 --localize ‘math.atan2’ for better performance

local function angleBetween( srcX, srcY, dstX, dstY )
local angle = ( math_deg( math_atan2( dstY-srcY, dstX-srcX ) )+90 ) --; return angle
if ( angle < 0 ) then angle = angle + 360 end ; return angle % 360
end

flies[#flies + 1] = display.newImageRect (“images/fly.png”, 30, 32)
local edge = math_random(1,4)

if (edge == 1) then
–top
flies[#flies].y = 0
flies[#flies].x = math_random(0, 480)
end
if (edge == 2) then
–bottom
flies[#flies].y = 320
flies[#flies].x = math_random(0, 480)
end
if (edge == 3) then
–left
flies[#flies].y = math_random(0, 320)
flies[#flies].x = 0
end
if (edge == 4) then
–right
flies[#flies].x = 480
flies[#flies].y = math_random(0, 320)
end

local ang = angleBetween( flies[#flies].x, flies[#flies].y, donut.x, donut.y )

flies[#flies].rotation = ang
physics.addBody( flies[#flies], “dynamic”, { density=1.0, friction=1.0, bounce=0, radius=10 } )

flyxdirection = donut.x - flies[#flies].x
flyydirection = donut.y - flies[#flies].y
flies[#flies]:setLinearVelocity( flyxdirection*speed, flyydirection*speed )
flies[#flies].collision = reachdonut

flies[#flies]:addEventListener( “collision” )
flies[#flies]:addEventListener( “tap”, die )

sceneGroup:insert(flies[#flies])
return flies[#flies]

end

myTimer = timer.performWithDelay(1000, spawn, 10)

– Called when the scene’s view does not exist

– INSERT code here to initialize the scene
– e.g. add display objects to ‘sceneGroup’, add touch listeners, etc
end

function scene:show( event )
local phase = event.phase

if ( phase == “will” ) then

– Called when the scene is still off screen (but is about to come on screen).
elseif ( phase == “did” ) then
– Called when the scene is now on screen.
– Insert code here to make the scene come alive.
– Example: start timers, begin animation, play audio, etc.
local sceneGroup = self.view
end

end

function scene:hide( event )
local sceneGroup = self.view

end

function scene:destroy( event )
local sceneGroup = self.view

bg:removeSelf()
bg = nil
donut:removeSelf()
donut = nil

for k=#flies, 1, -1 do
flies[k].isVisible = false
flies[k]:removeEventListener( “tap”, die )
flies[k]:removeEventListener( “collision”, reachdonut )
flies[k]:removeSelf()
flies[k] = nil
table.remove(flies,k)
end
for k=#stuckflies, 1, -1 do
stuckflies[k].isVisible = false
stuckflies[k]:removeSelf()
stuckflies[k] = nil
table.remove(stuckflies,k)
end
for k=#blood, 1, -1 do
blood[k].isVisible = false
blood[k]:blood()
blood[k] = nil
table.remove(blood,k)
end
if myTimer ~= nil then
timer.cancel(myTimer)
myTimer = nil
end

– Called prior to the removal of scene’s “view” (sceneGroup)

– INSERT code here to cleanup the scene
– e.g. remove display objects, remove touch listeners, save state, etc
end


– Listener setup
scene:addEventListener( “create”, scene )
scene:addEventListener( “show”, scene )
scene:addEventListener( “hide”, scene )
scene:addEventListener( “destroy”, scene )


return scene
[/lua]

Further Ive added prints everywhere and it doesn’t seem that the scene:destroy function is ever called. What would be stopping it? Also the timerperformwithdelay seems to continue even after being niled out

The scene:destroy() function is called when composer.removeScene() is called on that scene. It will execute this function first, giving you time to dispose of any audio that you may have loaded, remove any display objects that ***were not*** inserted into the scene’s view group or dispose of anything the scene isn’t managing.

You do not need to remove display objects yourself. If they are in the scene’s view group, Composer will manage their removal. Unless you need to dispose audio that was loaded in scene:create() or the main chunk, you generally don’t have to do anything in scene:destroy(). If you find that objects are staying on the screen after you move to a new scene, then you didn’t insert them into the scene’s view group in the first place.

If Composer is managing your objects, tap, touch, and collision event listeners on the object will be removed when composer.removeScene() is called. Also once these objects are off screen (via a Composer transition) that can’t be interacted with. Even then you should be adding them in scene:show() and removing them in scene:hide() (in case you do a fade/crossFade and they are sitting  underneath the current scene).

The easiest way to reset a scene is to go to a cut scene (next level or you lost) and in that scene do a composer.removeScene(“game”) or whatever  you named the scene you want to reset.

The other way is a lot more work. You will need a reset function that moves everything to it’s starting position, resets any scores, hit points, rotation, etc. and then call your startGame() function since you’re not going to be using Composer to reset the scene.  Initially when scene:show() is called in it’s did phase, it would call your startGame() function.

Rob

I understood that the scene was wiped automatically. Didn’t realise I had to call composer.removeScene

The view can be wiped automatically if you set the recycleOnSceneChange attribute to true, but it only dumps the view and display objects. Any thing you’ve done in the main chunk like initializing variables won’t be re-initialized until the module is un-required. composer.removeScene() will un-require the module giving you a clean start.

Rob

The code most of your code above scene create needs to go inside scene create.

Hi,

I’ve tried to move everything into the scene create function but still no luck

[lua]---------------------------------------------------------------------------------

– game.lua


local sceneName = …

local composer = require( “composer” )
local physics = require(“physics”)
physics.start();
physics.setGravity( 0, 0 )

– Load scene with same root filename as this file
local scene = composer.newScene( sceneName )


function scene:create( event )
local sceneGroup = self.view

local bg
local donut
local fly1
local fly2
local fly3
local flies = {}
local stuckflies = {}
local blood = {}
local speed = 0.5
local math_random = math.random
local endflag = false
local myTimer

bg = display.newImageRect (“images/bg.png”, 570, 360)
bg.x =display.contentWidth*0.5
bg.y = display.contentHeight*0.5

donut = display.newImageRect (“images/donut.png”, 75, 75)
donut.x =display.contentWidth*0.5
donut.y = display.contentHeight*0.5

physics.addBody( donut, “static”, { density=1.0, friction=1.0, bounce=0, radius=25 } )

fly1 = display.newImageRect (“images/fly.png”, 32, 30)
fly1.x = 30
fly1.y = 25

fly2 = display.newImageRect (“images/fly.png”, 32, 30)
fly2.x = 70
fly2.y = 25

fly3 = display.newImageRect (“images/fly.png”, 32, 30)
fly3.x = 110
fly3.y = 25

–Insert into groups

sceneGroup:insert (bg)
sceneGroup:insert (donut)
sceneGroup:insert (fly1)
sceneGroup:insert (fly2)
sceneGroup:insert (fly3)

local function die(event)
local fly = event.target
blood[#blood + 1] = display.newImageRect (“images/blood.png”, 30, 31)
blood[#blood].x = fly.x
blood[#blood].y = fly.y

sceneGroup:insert(blood[#blood])

for k=#flies, 1, -1 do
if (flies[k] == fly) then
flies[k].isVisible = false;
flies[k]:removeEventListener( “tap”, die )
flies[k]:removeEventListener( “collision”, reachdonut )
flies[k]:removeSelf();
flies[k] = nil
table.remove(flies,k);

end
end
return blood[#blood]
end

local function reachdonut(self, event)

if (fly3) then
fly3:removeSelf()
fly3 = nil
elseif (fly2) then
fly2:removeSelf()
fly2 = nil
elseif (fly1) then
fly1:removeSelf()
fly1 = nil
endflag = true
end

stuckflies[#stuckflies + 1] = display.newImageRect (“images/fly.png”, 30, 32)
stuckflies[#stuckflies].x = self.x
stuckflies[#stuckflies].y = self.y
stuckflies[#stuckflies].rotation = self.rotation

sceneGroup:insert(stuckflies[#stuckflies])

for k=#flies, 1, -1 do
if (flies[k] == self) then
flies[k].isVisible = false;
flies[k]:removeEventListener( “tap”, die )
flies[k]:removeEventListener( “collision”, reachdonut )
flies[k]:removeSelf();
flies[k] = nil
table.remove(flies,k);

end
end

if (endflag == true) then

composer.gotoScene( “gameover”)
end
return stuckflies[#stuckflies]
end

local function spawn()

local math_deg = math.deg --localize ‘math.deg’ for better performance
local math_atan2 = math.atan2 --localize ‘math.atan2’ for better performance

local function angleBetween( srcX, srcY, dstX, dstY )
local angle = ( math_deg( math_atan2( dstY-srcY, dstX-srcX ) )+90 ) --; return angle
if ( angle < 0 ) then angle = angle + 360 end ; return angle % 360
end

flies[#flies + 1] = display.newImageRect (“images/fly.png”, 30, 32)
local edge = math_random(1,4)

if (edge == 1) then
–top
flies[#flies].y = 0
flies[#flies].x = math_random(0, 480)
end
if (edge == 2) then
–bottom
flies[#flies].y = 320
flies[#flies].x = math_random(0, 480)
end
if (edge == 3) then
–left
flies[#flies].y = math_random(0, 320)
flies[#flies].x = 0
end
if (edge == 4) then
–right
flies[#flies].x = 480
flies[#flies].y = math_random(0, 320)
end

local ang = angleBetween( flies[#flies].x, flies[#flies].y, donut.x, donut.y )

flies[#flies].rotation = ang
physics.addBody( flies[#flies], “dynamic”, { density=1.0, friction=1.0, bounce=0, radius=10 } )

flyxdirection = donut.x - flies[#flies].x
flyydirection = donut.y - flies[#flies].y
flies[#flies]:setLinearVelocity( flyxdirection*speed, flyydirection*speed )
flies[#flies].collision = reachdonut

flies[#flies]:addEventListener( “collision” )
flies[#flies]:addEventListener( “tap”, die )

sceneGroup:insert(flies[#flies])
return flies[#flies]

end

myTimer = timer.performWithDelay(1000, spawn, 10)

– Called when the scene’s view does not exist

– INSERT code here to initialize the scene
– e.g. add display objects to ‘sceneGroup’, add touch listeners, etc
end

function scene:show( event )
local phase = event.phase

if ( phase == “will” ) then

– Called when the scene is still off screen (but is about to come on screen).
elseif ( phase == “did” ) then
– Called when the scene is now on screen.
– Insert code here to make the scene come alive.
– Example: start timers, begin animation, play audio, etc.
local sceneGroup = self.view
end

end

function scene:hide( event )
local sceneGroup = self.view

end

function scene:destroy( event )
local sceneGroup = self.view

bg:removeSelf()
bg = nil
donut:removeSelf()
donut = nil

for k=#flies, 1, -1 do
flies[k].isVisible = false
flies[k]:removeEventListener( “tap”, die )
flies[k]:removeEventListener( “collision”, reachdonut )
flies[k]:removeSelf()
flies[k] = nil
table.remove(flies,k)
end
for k=#stuckflies, 1, -1 do
stuckflies[k].isVisible = false
stuckflies[k]:removeSelf()
stuckflies[k] = nil
table.remove(stuckflies,k)
end
for k=#blood, 1, -1 do
blood[k].isVisible = false
blood[k]:blood()
blood[k] = nil
table.remove(blood,k)
end
if myTimer ~= nil then
timer.cancel(myTimer)
myTimer = nil
end

– Called prior to the removal of scene’s “view” (sceneGroup)

– INSERT code here to cleanup the scene
– e.g. remove display objects, remove touch listeners, save state, etc
end


– Listener setup
scene:addEventListener( “create”, scene )
scene:addEventListener( “show”, scene )
scene:addEventListener( “hide”, scene )
scene:addEventListener( “destroy”, scene )


return scene
[/lua]

Further Ive added prints everywhere and it doesn’t seem that the scene:destroy function is ever called. What would be stopping it? Also the timerperformwithdelay seems to continue even after being niled out

The scene:destroy() function is called when composer.removeScene() is called on that scene. It will execute this function first, giving you time to dispose of any audio that you may have loaded, remove any display objects that ***were not*** inserted into the scene’s view group or dispose of anything the scene isn’t managing.

You do not need to remove display objects yourself. If they are in the scene’s view group, Composer will manage their removal. Unless you need to dispose audio that was loaded in scene:create() or the main chunk, you generally don’t have to do anything in scene:destroy(). If you find that objects are staying on the screen after you move to a new scene, then you didn’t insert them into the scene’s view group in the first place.

If Composer is managing your objects, tap, touch, and collision event listeners on the object will be removed when composer.removeScene() is called. Also once these objects are off screen (via a Composer transition) that can’t be interacted with. Even then you should be adding them in scene:show() and removing them in scene:hide() (in case you do a fade/crossFade and they are sitting  underneath the current scene).

The easiest way to reset a scene is to go to a cut scene (next level or you lost) and in that scene do a composer.removeScene(“game”) or whatever  you named the scene you want to reset.

The other way is a lot more work. You will need a reset function that moves everything to it’s starting position, resets any scores, hit points, rotation, etc. and then call your startGame() function since you’re not going to be using Composer to reset the scene.  Initially when scene:show() is called in it’s did phase, it would call your startGame() function.

Rob

I understood that the scene was wiped automatically. Didn’t realise I had to call composer.removeScene

The view can be wiped automatically if you set the recycleOnSceneChange attribute to true, but it only dumps the view and display objects. Any thing you’ve done in the main chunk like initializing variables won’t be re-initialized until the module is un-required. composer.removeScene() will un-require the module giving you a clean start.

Rob