If/Else does not work after the scene is reloaded

Hello. I apologize in advance for my English.

I have simple game algoritm:

Menu -> Game (The player needs to react in time and press the desired button on display) -> 

if the player has time to react-> win screen -> back to Game (with button)

if the player does not have time to react -> lose screen -> back to Game (with button) 

The essence of the problem:

I have function, that blocks up to a certain time the button necessary to achieve victory (win screen)

function Blockbtn(event) if enemyrun then alphawinbtn.isHitTestable = true else alphawinbtn.isHitTestable = false end end Runtime:addEventListener("enterFrame", Blockbtn)

So, when I run the game in the simulator for the first time, everything works fine and I can not reach the victory ahead of time, but when the game scene reboots it loads from the lose screen, for some reason I have the opportunity to click on the “alphawinbtn” button and, accordingly, go to  win screen

Can you show us how you reboot the scene?  Also the code that takes you to the win or lose screens.

win/lose screens

game.lua

enemyrun = timer.performWithDelay( mRand(100 , 650) , gotoLosescreen, 1) function Blockbtn(event) if enemyrun then alphawinbtn.isHitTestable = true else alphawinbtn.isHitTestable = false end end Runtime:addEventListener("enterFrame", Blockbtn) end function gotoLosescreen() composer.removeScene( "game" , false) composer.gotoScene( "losescreen" ) end --win function gotoWinscreen() composer.removeScene( "game", false ) composer.gotoScene( "winscreen" ) end local function Win() timer.cancel( enemyrun ) timer.performWithDelay( 100, gotoWinscreen) end alphawinbtn = display.newRect(mainGroup, 0, 0, 480, 100) alphawinbtn.x = display.contentCenterX alphawinbtn.y = display.contentCenterY +80 alphawinbtn.alpha = 0 alphawinbtn:addEventListener("tap", Win, 1)

reboot scene:

game.lua 

-- hide() function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then -- Code here runs when the scene is on screen (but is about to go off screen) elseif ( phase == "did" ) then -- Code here runs immediately after the scene goes entirely off screen timer.cancel( enemyrun ) Runtime:removeEventListener("enterFrame", Blockbtn) composer.removeScene( "game", true) end end

lose screen

function scene:show( event )

local sceneGroup = self.view

local phase = event.phase

if ( phase == “will” ) then

–Сцена выключена но скоро появится на экран

elseif ( phase == “did” ) then

– Сцена полностью загружена на экран

local objectGroup = display.newGroup()

local function gotoGame()

composer.loadScene( “game” )

end

background = display.newImageRect(objectGroup,“pics/losescreen.png” , 480 , 320)

background.x = display.contentCenterX

background.y = display.contentCenterY

local getback = display.newRect(objectGroup, 0, 0, 480, 320 )

getback.x = display.contentCenterX

getback.y = display.contentCenterY

 getback:setFillColor( 0.75, 0.78, 1 )

 getback.alpha = 0.01

 getback:addEventListener( “tap”, gotoGame )

end

end

– Скрытие сцены

function scene:hide( event )

local sceneGroup = self.view

local phase = event.phase

if ( phase == “will” ) then

– выполняется перед скрытием сцены

elseif ( phase == “did” ) then

– выполняется после скрытия сцены

composer.removeScene( “losescreen” )

end

end

win screen 

function scene:create( event ) local sceneGroup = self.view -- Выполняется при создании сцены, до ее загрузки end -- Отображение сцены function scene:show( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then --Сцена выключена но скоро появится на экран elseif ( phase == "did" ) then -- Сцена полностью загружена на экран local objectGroup = display.newGroup() local function gotoGame() composer.loadScene( "game" ) end background = display.newImageRect(objectGroup,"pics/winscreen.png" , 480 , 320) background.x = display.contentCenterX background.y = display.contentCenterY local getback = display.newRect(objectGroup, 0, 0, 480, 320 ) getback.x = display.contentCenterX getback.y = display.contentCenterY getback:setFillColor( 0.75, 0.78, 1 ) getback.alpha = 0.01 getback:addEventListener( "tap", gotoGame ) end end -- Скрытие сцены function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then -- выполняется перед скрытием сцены elseif ( phase == "did" ) then -- выполняется после скрытия сцены composer.removeScene( "winscreen" ) end end -- уничтожение сцены() function scene:destroy( event ) local sceneGroup = self.view -- код выполняется до удаления сцены end

It seems to me that the “enemyrun” timer is what takes you to the lose screen right?  How so you reload that timer?  Is there a reason the timer is global rather than local?

[lua]

enemyrun = timer.performWithDelay( mRand(100 , 650) , gotoLosescreen, 1)

[/lua]

I’m guessing that you will need to put some sort of control mechanism on when the timer activates.  By the time the scene reloads, they enemyrun timer might have already instructed the composer to go to the lose screen.  Making the timer local instead of global might also help you contain it.  

At first I wanted to say that I already have a control mechanism.

And this is essentially true, but when I took a closer look at him, I saw that he was in the zone of another function:

local mRand = math.random swish = audio.loadSound( "sound/swish.wav" ) --change sky color function SkyChangeColor() audio.play (swish) display.remove( back) \_G.blood = display.newImageRect(mainGroup, "pics/redsky.png", 480, 320 ) blood.x = display.contentCenterX blood.y = display.contentCenterY blood:toBack() --the enemy begins an attack enemyrun = timer.performWithDelay( mRand(1000 , 1650) , gotoLosescreen, 1) function Blockbtn() if enemyrun then alphawinbtn.isHitTestable = true else alphawinbtn.isHitTestable = false end end Runtime:addEventListener("enterFrame", Blockbtn) end --get "random" time for call change sky color function timerSkyChangeColor = timer.performWithDelay( mRand(5500 , 7000), SkyChangeColor )

Then I rendered this mechanism outside of the function and it kind of helped. Only now my button is locked permanently and I can not win in my game: with

And timer “enemyrun” is not local because it is referenced by the timer.cancel (enemyrun), and when I make it local, I get an error.

In general, could you look at my “mechanism” and say whether it is correct?

--I understand that this works like this: function Blockbtn() --if enemyrun timer started, then button, which leads to the win screen can be used if enemyrun then alphawinbtn.isHitTestable = true --And until the start of the timer, it can not be used (so that you can not achieve win screen ahead of time) else alphawinbtn.isHitTestable = false end

Try putting a local “enemyrun” timer in an “enemyAttacks” function and then cancelling that timer in the “gotoLosescreen” function.

That way you can decide exactly when the enemy starts attacking by calling enemyAttacks()

[lua]

local function gotoLosescreen(e)

    print( "Killing "… e.source.name)

    timer.cancel( e.source ) ; e.source = nil

    composer.removeScene( “game” , false)

    composer.gotoScene( “losescreen” )

end

local function enemyAttacks(  )

    local enemyrun = timer.performWithDelay( math.random(1000 , 1650) , gotoLosescreen, 1)

    enemyrun.name = “enemy run timer”

end

enemyAttacks()

[/lua]

Can you show us how you reboot the scene?  Also the code that takes you to the win or lose screens.

win/lose screens

game.lua

enemyrun = timer.performWithDelay( mRand(100 , 650) , gotoLosescreen, 1) function Blockbtn(event) if enemyrun then alphawinbtn.isHitTestable = true else alphawinbtn.isHitTestable = false end end Runtime:addEventListener("enterFrame", Blockbtn) end function gotoLosescreen() composer.removeScene( "game" , false) composer.gotoScene( "losescreen" ) end --win function gotoWinscreen() composer.removeScene( "game", false ) composer.gotoScene( "winscreen" ) end local function Win() timer.cancel( enemyrun ) timer.performWithDelay( 100, gotoWinscreen) end alphawinbtn = display.newRect(mainGroup, 0, 0, 480, 100) alphawinbtn.x = display.contentCenterX alphawinbtn.y = display.contentCenterY +80 alphawinbtn.alpha = 0 alphawinbtn:addEventListener("tap", Win, 1)

reboot scene:

game.lua 

-- hide() function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then -- Code here runs when the scene is on screen (but is about to go off screen) elseif ( phase == "did" ) then -- Code here runs immediately after the scene goes entirely off screen timer.cancel( enemyrun ) Runtime:removeEventListener("enterFrame", Blockbtn) composer.removeScene( "game", true) end end

lose screen

function scene:show( event )

local sceneGroup = self.view

local phase = event.phase

if ( phase == “will” ) then

–Сцена выключена но скоро появится на экран

elseif ( phase == “did” ) then

– Сцена полностью загружена на экран

local objectGroup = display.newGroup()

local function gotoGame()

composer.loadScene( “game” )

end

background = display.newImageRect(objectGroup,“pics/losescreen.png” , 480 , 320)

background.x = display.contentCenterX

background.y = display.contentCenterY

local getback = display.newRect(objectGroup, 0, 0, 480, 320 )

getback.x = display.contentCenterX

getback.y = display.contentCenterY

 getback:setFillColor( 0.75, 0.78, 1 )

 getback.alpha = 0.01

 getback:addEventListener( “tap”, gotoGame )

end

end

– Скрытие сцены

function scene:hide( event )

local sceneGroup = self.view

local phase = event.phase

if ( phase == “will” ) then

– выполняется перед скрытием сцены

elseif ( phase == “did” ) then

– выполняется после скрытия сцены

composer.removeScene( “losescreen” )

end

end

win screen 

function scene:create( event ) local sceneGroup = self.view -- Выполняется при создании сцены, до ее загрузки end -- Отображение сцены function scene:show( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then --Сцена выключена но скоро появится на экран elseif ( phase == "did" ) then -- Сцена полностью загружена на экран local objectGroup = display.newGroup() local function gotoGame() composer.loadScene( "game" ) end background = display.newImageRect(objectGroup,"pics/winscreen.png" , 480 , 320) background.x = display.contentCenterX background.y = display.contentCenterY local getback = display.newRect(objectGroup, 0, 0, 480, 320 ) getback.x = display.contentCenterX getback.y = display.contentCenterY getback:setFillColor( 0.75, 0.78, 1 ) getback.alpha = 0.01 getback:addEventListener( "tap", gotoGame ) end end -- Скрытие сцены function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then -- выполняется перед скрытием сцены elseif ( phase == "did" ) then -- выполняется после скрытия сцены composer.removeScene( "winscreen" ) end end -- уничтожение сцены() function scene:destroy( event ) local sceneGroup = self.view -- код выполняется до удаления сцены end

It seems to me that the “enemyrun” timer is what takes you to the lose screen right?  How so you reload that timer?  Is there a reason the timer is global rather than local?

[lua]

enemyrun = timer.performWithDelay( mRand(100 , 650) , gotoLosescreen, 1)

[/lua]

I’m guessing that you will need to put some sort of control mechanism on when the timer activates.  By the time the scene reloads, they enemyrun timer might have already instructed the composer to go to the lose screen.  Making the timer local instead of global might also help you contain it.  

At first I wanted to say that I already have a control mechanism.

And this is essentially true, but when I took a closer look at him, I saw that he was in the zone of another function:

local mRand = math.random swish = audio.loadSound( "sound/swish.wav" ) --change sky color function SkyChangeColor() audio.play (swish) display.remove( back) \_G.blood = display.newImageRect(mainGroup, "pics/redsky.png", 480, 320 ) blood.x = display.contentCenterX blood.y = display.contentCenterY blood:toBack() --the enemy begins an attack enemyrun = timer.performWithDelay( mRand(1000 , 1650) , gotoLosescreen, 1) function Blockbtn() if enemyrun then alphawinbtn.isHitTestable = true else alphawinbtn.isHitTestable = false end end Runtime:addEventListener("enterFrame", Blockbtn) end --get "random" time for call change sky color function timerSkyChangeColor = timer.performWithDelay( mRand(5500 , 7000), SkyChangeColor )

Then I rendered this mechanism outside of the function and it kind of helped. Only now my button is locked permanently and I can not win in my game: with

And timer “enemyrun” is not local because it is referenced by the timer.cancel (enemyrun), and when I make it local, I get an error.

In general, could you look at my “mechanism” and say whether it is correct?

--I understand that this works like this: function Blockbtn() --if enemyrun timer started, then button, which leads to the win screen can be used if enemyrun then alphawinbtn.isHitTestable = true --And until the start of the timer, it can not be used (so that you can not achieve win screen ahead of time) else alphawinbtn.isHitTestable = false end

Try putting a local “enemyrun” timer in an “enemyAttacks” function and then cancelling that timer in the “gotoLosescreen” function.

That way you can decide exactly when the enemy starts attacking by calling enemyAttacks()

[lua]

local function gotoLosescreen(e)

    print( "Killing "… e.source.name)

    timer.cancel( e.source ) ; e.source = nil

    composer.removeScene( “game” , false)

    composer.gotoScene( “losescreen” )

end

local function enemyAttacks(  )

    local enemyrun = timer.performWithDelay( math.random(1000 , 1650) , gotoLosescreen, 1)

    enemyrun.name = “enemy run timer”

end

enemyAttacks()

[/lua]