spawn same display object and memory management

Hi,

I spawn objects and clean up as below but there seem to be memory leak.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
local function spawnBomb()
   local bomb = display.newImage("bomb.png")
   bombs[bomb] = bomb
   bombs[bomb].x = math.random(_W/2, _W/2)
   bombs[bomb].name = "bomb"
   physics.addBody(bombs[bomb], {bounce=0})
   bombs[bomb].bodyType = "kinematic"
   bombs[bomb].isSensor = true
   bombs[bomb].y = math.random(-100, -10)
   bombGroup:insert(bombs[bomb])
   bombs[bomb]:setLinearVelocity(0, math.random(100, 110))
        function onCollision(e)
           if e.phase == "began" then
                bombs[bomb]:removeSelf()
                bombs[bomb] = nil
           end
        end
        bombs[bomb]:addEventListener("collision", onCollision)
end
tmrSpawnBomb = timer.performWithDelay(200, spawnBomb, 0)
 
 
local function cleanUp()
 
    if bombGroup.numChildren then
        for i=bombGroup.numChildren, 1, -1 do
           if bombGroup[i].y > 150 then
             bombGroup[i]:removeEventListener("collision", onCollision)
              bombGroup[i]:removeSelf()
 
           end
        end
     end
end
tmrCheckBubble = timer.performWithDelay(20, cleanUp, 0)

I think the cleanUp function only remove the display object, but the table structure of the object is there unless we set the object to nil, thus causing the memory leak.

 bombGroup[i] = nil will generate WARNING: Attempting to set property(1) with nil.

How to set object to nil with such cleapUp function or any other function? Is there a better way to spawn objects with the same file name and object name and clean it up after its Y or X exceed certain point?

Steve

This part here;

1
2
3
4
5
6
function onCollision(e)
           if e.phase == "began" then
                bombs[bomb]:removeSelf()
                bombs[bomb] = nil
           end
        end

Thanks, Peach Pellen. Thought I don't have the delay, it doesn't make any error at the moment but to be safe I'll add delay timer. How about cleanUp function? Does it make sense?

Steve

Hi. This is how you should be doing your spawns...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
local function spawnBomb()
   local bomb = display.newImage("bomb.png")
   bomb.x = math.random(_W/2, _W/2)
   bomb.name = "bomb"
   physics.addBody(bomb, {bounce=0})
   bomb.bodyType = "kinematic"
   bomb.isSensor = true
   bomb.y = math.random(-100, -10)
   bomb.index = #bombs + 1
   bombGroup:insert(bomb)
 
   bomb:setLinearVelocity(0, math.random(100, 110))
        function onCollision(e)
           if e.phase == "began" then
                bomb:removeSelf()
                bomb = nil
           end
        end
        bomb:addEventListener("collision", onCollision)
 
        bombs[bomb.index] = bomb
 
        return bomb
 
end

@Danny, how can I remove bomb when it goes off screen? I can do it by setting up an off screen object to collide with bomb, but is there any other ways? Thank you.

Steve

The way you suggested is probably the best way.

However you can also remove them this way (in a for loop, in a runtime listener)

1
2
3
4
5
6
7
8
for i, v in pairs(bombs) do
    --if bomb leaves right side of screen
    if bombs[i].x + bombs[i].width / 2 > display.contentWidth then
        bombs[i]:removeSelf()
        table.remove(bombs, i)
        bombs[i] = nil
     end
end

@Danny, it removes the object if there is only one passing the threshold line, but if there are more, some are not removed. I put together the code below for your review just in case I've done something wrong.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
_W = display.contentWidth
_H = display.contentHeight
local physics = require("physics")
physics.start()
local bombs = {}
local bombGroup = display.newGroup()
 
local function spawnBomb()
   local bomb = display.newImage("bomb.png")
   bomb.x = math.random(0, _W)
   bomb.name = "bomb"
   physics.addBody(bomb, {bounce=0, filter=b})
   bomb.bodyType = "kinematic"
   bomb.isSensor = true
   bomb.y = math.random(-100, -10)
   bomb.index = #bombs + 1
   bombGroup:insert(bomb)
   bomb:setLinearVelocity(0, math.random(100, 110))
        function onCollision(e)
           if e.phase == "began" then
                        hello()
                bomb:removeSelf()
                bomb = nil
           end
        end
        bomb:addEventListener("collision", onCollision)
 
        bombs[bomb.index] = bomb
 
        return bomb
 
end
tmrSpawnBomb = timer.performWithDelay(1000, spawnBomb, 0)
 
 
local function removeBomb()
for i, v in pairs(bombs) do
    if bombs[i].y >100 then
        bombs[i]:removeSelf()
        table.remove(bombs, i)
        bombs[i] = nil
     end
end
end
Runtime:addEventListener("enterFrame", removeBomb)
views:1747 update:2011/9/26 8:07:09
corona forums © 2003-2011