Map not destroyed?

Hi there… I noticed some strange behavior regarding the map destruction and want to ask if someone else having this problem maybe:

I’m using this code inside of a composer scenes scene:destroy( event )

    if map then         map.destroy()         map=nil     end

Now I’m starting the same scene again by calling a “clean” scene, which then calls the scene from before. Inside the clean scene I’m using composer.removeScene( “scenefrombefore” ) to make sure the scene:destroy( event ) is called and the code from above now should clean the map.

Somehow this doesn’t seem the case here because I still get some values from map objects which was added in the map from the first start of the scene.

I have fixed this by adding the code from above directly before the creation of the map and then it seems to work fine.

But shouldn’t this also work inside of scene:destroy( event ) when using composer.removeScene?

Hm. Can you give me some examples of what exactly is “carrying over”? Are you loading the map with dusk.loadMap before building it?

  • Caleb

I still wasn’t able to figure out exactly why the value was carried over (or where exactly), but maybe I found out why the map was still there… I have used this to load the map in a scene with requiring dusk in main.lua before.

_G.dusk.buildMap

So maybe it is not a good idea to to this on a global level here. (didn’t try this yet with requiring dusk in the same scene an not doing it global!)

Okay… I encountered another issue based on this problem I guess.

Here are some details:

I have a TILED layer named “WaterLayer” in my map in only some levels. Other levels doesn’t have this layer.

It can happen I change from a composer scene loading a map level which was showing a WaterLayer to a map level which is not using a WaterLayer.

Before I’m building a new map level I’m using this code:

if map then         map.destroy()         map=nil end

Then I build my new dusk map without the WaterLayer.

BUT: Somehow an image I put via insert into the WaterLayer in the first scene is accessed in the new scene without the WaterLayer.

This is happening like this:

In the first scene I’m inserting an image in the WaterLayer. I also keep track of inserted images and remove them between a scene change. Now in the new scene (the one after the images should be removed, the map destroyed, a new map was build with NO WaterLayer) the images values, like for example the Image.x value for the x position can not be accessed BUT code inside of this:

if image~=nil then     -- do something end

seems like it still is accessed. Because I’m using a contentBounds function in this if clause which is done on the image and causing an error.

Shouldn’t the image inside the WaterLayer be removed with the map destruction?

Are you sure that image isn’t a global variable? Try printing _G.image to see.

  • Caleb

I’ve already changed the code, so I can’t test this fast… but will later. I’m sure it is not a global variable.

To prevent the check and the contentBounds action on the image I now check for the layer first if it exists like this:

if var.map.layer["WaterLayer"] then     -- do the contentBound stuff on the image here end

This is working. The check for the image itself wasn’t.

Will look into it!

Thank you for your help!

Yep, that points to some problem with scoping or not nil-ing out the image. If the Dusk layer doesn’t exist, I can assure you the image doesn’t ;).

  • Caleb

thank you!

one more thing then… :slight_smile: … what is the best way to destroy and nil image files if they are created at top of an external module which is required in a level composer scene. The image files are created like this:

extern module “extmodule.lua”:

mod={} local gfx={image1,image2,image3} local init= function()      gfx.image1=display.newRect(...)      gfx.image2=display.newRect(...)      gfx.image3=display.newRect(...) end mod.gfx=gfx return mod

And in the scene it is used like this:

local ext=require ("extmodule") local gfx=ext.gfx -- do stuff with the images in the scenes like this: -- gfx.image1.x=200 -- gfx.image1.y=100 -- ...

And then I destroy the images, when the scene has left the screen completely in the composer scene status before the destroy status like this:

for k,v in pairs( gfx ) do             if v then                 display.remove ( v )                 v=nil             end end

Shouldn’t this delete everything?

What about using a function somewhere sending the image to like this:

local dosomething = function (image)      image.x=300 end dosomething(gfx.image1)

And is there a difference regarding the images destruction (as seen above) when the function in the last part above is created at top of an external module like you can see below… I guess maybe the function stays in memory maybe then because the local call at top local func={dosomething} is not accessed each time the external module is loaded, but only the first time, right?

local func={dosomething} func.dosomething=function(image)      image.x=300 end func.dosomething(gfx.image1)

So could it be the use of the last function causing the problems? Holding the image in memory as an instance with “image” inside the function? Even when gfx.image1 etc. are destroyed?

This would explain the water problem.

Well, function arguments and local variables in functions don’t stay around past the function’s scope, so it wouldn’t be that. However, when you’re using the k, v loop to remove stuff, you’re setting v to nil but not gfx[k] to nil. v here is just a reference to the object, and when you delete it, there remains the reference inside gfx. You’ll need to set gfx[k] to nil after removing the image to nil the reference in gfx.

  • Caleb

Thank you! This really was helpful!!!

Hm. Can you give me some examples of what exactly is “carrying over”? Are you loading the map with dusk.loadMap before building it?

  • Caleb

I still wasn’t able to figure out exactly why the value was carried over (or where exactly), but maybe I found out why the map was still there… I have used this to load the map in a scene with requiring dusk in main.lua before.

_G.dusk.buildMap

So maybe it is not a good idea to to this on a global level here. (didn’t try this yet with requiring dusk in the same scene an not doing it global!)

Okay… I encountered another issue based on this problem I guess.

Here are some details:

I have a TILED layer named “WaterLayer” in my map in only some levels. Other levels doesn’t have this layer.

It can happen I change from a composer scene loading a map level which was showing a WaterLayer to a map level which is not using a WaterLayer.

Before I’m building a new map level I’m using this code:

if map then         map.destroy()         map=nil end

Then I build my new dusk map without the WaterLayer.

BUT: Somehow an image I put via insert into the WaterLayer in the first scene is accessed in the new scene without the WaterLayer.

This is happening like this:

In the first scene I’m inserting an image in the WaterLayer. I also keep track of inserted images and remove them between a scene change. Now in the new scene (the one after the images should be removed, the map destroyed, a new map was build with NO WaterLayer) the images values, like for example the Image.x value for the x position can not be accessed BUT code inside of this:

if image~=nil then     -- do something end

seems like it still is accessed. Because I’m using a contentBounds function in this if clause which is done on the image and causing an error.

Shouldn’t the image inside the WaterLayer be removed with the map destruction?

Are you sure that image isn’t a global variable? Try printing _G.image to see.

  • Caleb

I’ve already changed the code, so I can’t test this fast… but will later. I’m sure it is not a global variable.

To prevent the check and the contentBounds action on the image I now check for the layer first if it exists like this:

if var.map.layer["WaterLayer"] then     -- do the contentBound stuff on the image here end

This is working. The check for the image itself wasn’t.

Will look into it!

Thank you for your help!

Yep, that points to some problem with scoping or not nil-ing out the image. If the Dusk layer doesn’t exist, I can assure you the image doesn’t ;).

  • Caleb

thank you!

one more thing then… :slight_smile: … what is the best way to destroy and nil image files if they are created at top of an external module which is required in a level composer scene. The image files are created like this:

extern module “extmodule.lua”:

mod={} local gfx={image1,image2,image3} local init= function()      gfx.image1=display.newRect(...)      gfx.image2=display.newRect(...)      gfx.image3=display.newRect(...) end mod.gfx=gfx return mod

And in the scene it is used like this:

local ext=require ("extmodule") local gfx=ext.gfx -- do stuff with the images in the scenes like this: -- gfx.image1.x=200 -- gfx.image1.y=100 -- ...

And then I destroy the images, when the scene has left the screen completely in the composer scene status before the destroy status like this:

for k,v in pairs( gfx ) do             if v then                 display.remove ( v )                 v=nil             end end

Shouldn’t this delete everything?

What about using a function somewhere sending the image to like this:

local dosomething = function (image)      image.x=300 end dosomething(gfx.image1)

And is there a difference regarding the images destruction (as seen above) when the function in the last part above is created at top of an external module like you can see below… I guess maybe the function stays in memory maybe then because the local call at top local func={dosomething} is not accessed each time the external module is loaded, but only the first time, right?

local func={dosomething} func.dosomething=function(image)      image.x=300 end func.dosomething(gfx.image1)

So could it be the use of the last function causing the problems? Holding the image in memory as an instance with “image” inside the function? Even when gfx.image1 etc. are destroyed?

This would explain the water problem.

Well, function arguments and local variables in functions don’t stay around past the function’s scope, so it wouldn’t be that. However, when you’re using the k, v loop to remove stuff, you’re setting v to nil but not gfx[k] to nil. v here is just a reference to the object, and when you delete it, there remains the reference inside gfx. You’ll need to set gfx[k] to nil after removing the image to nil the reference in gfx.

  • Caleb