timer.performWithDelay Function not effecting Image on scene re-enter

Hello everyone, I’ve got a tiny problem.

Basically a timer.performWithDelay function turns an ’ ImageA’ invisible after 10 seconds.
That’s fine and works.

But If I leave the scene and then re-enter it within the 10 seconds, the function runs but can’t find the ’ ImageA’ so it doesn’t get turned invisible.

I want this function to still effect the _ ImageA _ on scene re-enter.
Now the problem is because it isn’t actually the same image, since the last one was removed and nil’ed on scene exit.

Is there anyway to get it find the _ ImageA _ again, by looking for the same name/handle?

Cheers in advance folks. :slight_smile:

I think we need to see a bit of code. 

Fair enough, I’ll trim it of any unnecessary parts.
(I added in a lot of notes to help you, it looks a lot longer than it actually is! :stuck_out_tongue: )

 

module(..., package.seeall); function new() local localGroup = display.newGroup(); --Creation of a Rect that acts as a button. local buttonBuild = display.newRect(460,190,150,98); localGroup:insert(buttonBuild); --Creation of an image that begins invisible. When the above button is pressed it becomes --visible over the button, to let you know you can't build again.(Sort of Greyed out) local UnBuildable UnBuildable = display.newImageRect("Images/UnBuildable.png", 150, 100); UnBuildable:setReferencePoint(display.TopLeftReferencePoint); UnBuildable.x = 460; UnBuildable.y = 188; --If you are building already on scene entry, turn image visible (Can't build again yet) --Else turn invisible (You can build) if buildingProgress == 1 then UnBuildable.isVisible = true; else UnBuildable.isVisible = false; end --Function that occurs when building timer has finished. --Turns Unbuildable image invisible again & Resets buildingProgress variable. (You can build again) local function buildingBuilt() --Omitted: Several additions to variables - keep track of money, time cost. buildingProgress = 0; print("Building Constructed") UnBuildable.isVisible = false; end --Function that happens when you press the build button. Checks if your building already. --If not, deduct money and turn UnBuildable Image visible & Set buildingProgress == 1 (Can't build) --And begin timer until you can build again. local function buildingBuild(e) if(e.phase == "ended" and buildingProgress == 0) then --Omitted: Deduction of Money variables. buildingProgress = 1; print("--Build in Progress: Money Deducted--"); UnBuildable.isVisible = true; local constructTimer = timer.performWithDelay( timeVar, buildingBuilt, 1 ) end end buttonBuild:addEventListener("touch", buildingBuild); --Change Scene Function local function changeScene(e) if(e.phase == "ended") then --Some code to keep track of Tex Mem & CPU. print(collectgarbage("count")) local textMem = system.getInfo( "textureMemoryUsed" ) / 1000000 print( "TexMem: " .. textMem ) --Change Scene & Remove & Nil all objects in this scene and globals in case. director:changeScene(e.target.scene); package.loaded[Construction] = nil \_G[Construction] = nil end end button\_overview:addEventListener("touch", changeScene); return localGroup; end

When you leave the scene and come back it cannot find ‘UnBuildable’ and therefore can’t turn it’s image invisible again.
So it looks like you can’t build still. 
So it looks stuck, if you leave the scene again and come back it works like normal again because all the variables which determine whether it is invisible or not still work from the function.

It’s just if your on the scene at the time the function looks for UnBuildable, it can’t find it.

Does that help any?
Cheers!

I’m going to guess that because buildingProgress is a global it’s value is persisting between scenes and you never intialize it in your new() function.  Your logic leaves it set to 0 at the end, causing your graphic to be set to invisible.   I suspect that what you really want is:

[code]

if buildingProgress == 0 then
    UnBuildable.isVisible = true;
else
    UnBuildable.isVisible = false;
end

[/end]

You never initialize it, so the first time buildingProgress is nil and it will execute the false clause.  Since it’s global you might want to set it to 0 in your main.lua also.

But since the scene is being re-entered is there a reason why you just don’t set it to invisible right away?  Or can they leave the scene then come back before the timer finishes (which is a different bug you need to solve… If you change scenes that module gets unloaded and your timer will crash you because that function doesn’t exist any more).

buildingProgress is actually a local global variable sort of yes.
I do set it to 0 in the main.lua and it’s in: 

selfResourceData.lua

local table M = {}

And I call it in all the necessary places by:

local selfResourceData = require("selfResourceData");

and then selfResourceData.buildingProgress == 0 etc

Sorry I was just trying to simplify it down.

Yes they can leave and come back to the scene before the timer finishes, so it when you re-enter you’re still ‘building’ and so it sets the image visible, then the timer finishes and the function tries to set it invisible but can’t find it.

I took the liberty of recording and explaining my game to hopefully give you a better idea.
http://youtu.be/O6xsdr3NhrM

**How would the solution of checking on scene re-entry whether a timer is in progress, taking the time remaining and putting it into a new timer to do the same thing with the new scene and deleting the old timer. fair?

  • Essentially renewing the timer with a lesser time?**
     

I would either a) not have the code that manages the building (i.e. what the timer calls) as part of a scene, but as part of a module that is loaded and kept in memory.  Director (which is what I think you’re using) un-requires modules so code in there goes away. 

You could b ) stop the timers and save the completion time in your data.  When you come back check the current time vs the scheduled time and restart the timer if needed.

I think we need to see a bit of code. 

Fair enough, I’ll trim it of any unnecessary parts.
(I added in a lot of notes to help you, it looks a lot longer than it actually is! :stuck_out_tongue: )

 

module(..., package.seeall); function new() local localGroup = display.newGroup(); --Creation of a Rect that acts as a button. local buttonBuild = display.newRect(460,190,150,98); localGroup:insert(buttonBuild); --Creation of an image that begins invisible. When the above button is pressed it becomes --visible over the button, to let you know you can't build again.(Sort of Greyed out) local UnBuildable UnBuildable = display.newImageRect("Images/UnBuildable.png", 150, 100); UnBuildable:setReferencePoint(display.TopLeftReferencePoint); UnBuildable.x = 460; UnBuildable.y = 188; --If you are building already on scene entry, turn image visible (Can't build again yet) --Else turn invisible (You can build) if buildingProgress == 1 then UnBuildable.isVisible = true; else UnBuildable.isVisible = false; end --Function that occurs when building timer has finished. --Turns Unbuildable image invisible again & Resets buildingProgress variable. (You can build again) local function buildingBuilt() --Omitted: Several additions to variables - keep track of money, time cost. buildingProgress = 0; print("Building Constructed") UnBuildable.isVisible = false; end --Function that happens when you press the build button. Checks if your building already. --If not, deduct money and turn UnBuildable Image visible & Set buildingProgress == 1 (Can't build) --And begin timer until you can build again. local function buildingBuild(e) if(e.phase == "ended" and buildingProgress == 0) then --Omitted: Deduction of Money variables. buildingProgress = 1; print("--Build in Progress: Money Deducted--"); UnBuildable.isVisible = true; local constructTimer = timer.performWithDelay( timeVar, buildingBuilt, 1 ) end end buttonBuild:addEventListener("touch", buildingBuild); --Change Scene Function local function changeScene(e) if(e.phase == "ended") then --Some code to keep track of Tex Mem & CPU. print(collectgarbage("count")) local textMem = system.getInfo( "textureMemoryUsed" ) / 1000000 print( "TexMem: " .. textMem ) --Change Scene & Remove & Nil all objects in this scene and globals in case. director:changeScene(e.target.scene); package.loaded[Construction] = nil \_G[Construction] = nil end end button\_overview:addEventListener("touch", changeScene); return localGroup; end

When you leave the scene and come back it cannot find ‘UnBuildable’ and therefore can’t turn it’s image invisible again.
So it looks like you can’t build still. 
So it looks stuck, if you leave the scene again and come back it works like normal again because all the variables which determine whether it is invisible or not still work from the function.

It’s just if your on the scene at the time the function looks for UnBuildable, it can’t find it.

Does that help any?
Cheers!

I’m going to guess that because buildingProgress is a global it’s value is persisting between scenes and you never intialize it in your new() function.  Your logic leaves it set to 0 at the end, causing your graphic to be set to invisible.   I suspect that what you really want is:

[code]

if buildingProgress == 0 then
    UnBuildable.isVisible = true;
else
    UnBuildable.isVisible = false;
end

[/end]

You never initialize it, so the first time buildingProgress is nil and it will execute the false clause.  Since it’s global you might want to set it to 0 in your main.lua also.

But since the scene is being re-entered is there a reason why you just don’t set it to invisible right away?  Or can they leave the scene then come back before the timer finishes (which is a different bug you need to solve… If you change scenes that module gets unloaded and your timer will crash you because that function doesn’t exist any more).

buildingProgress is actually a local global variable sort of yes.
I do set it to 0 in the main.lua and it’s in: 

selfResourceData.lua

local table M = {}

And I call it in all the necessary places by:

local selfResourceData = require("selfResourceData");

and then selfResourceData.buildingProgress == 0 etc

Sorry I was just trying to simplify it down.

Yes they can leave and come back to the scene before the timer finishes, so it when you re-enter you’re still ‘building’ and so it sets the image visible, then the timer finishes and the function tries to set it invisible but can’t find it.

I took the liberty of recording and explaining my game to hopefully give you a better idea.
http://youtu.be/O6xsdr3NhrM

**How would the solution of checking on scene re-entry whether a timer is in progress, taking the time remaining and putting it into a new timer to do the same thing with the new scene and deleting the old timer. fair?

  • Essentially renewing the timer with a lesser time?**
     

I would either a) not have the code that manages the building (i.e. what the timer calls) as part of a scene, but as part of a module that is loaded and kept in memory.  Director (which is what I think you’re using) un-requires modules so code in there goes away. 

You could b ) stop the timers and save the completion time in your data.  When you come back check the current time vs the scheduled time and restart the timer if needed.