I’m a relative newbie to Corona but have worked with Codea before (and so am reasonably familiar with lua). I’m trying to get the hang of object deletion in Corona, since it works very differently to Codea. I have some “bullet” code that creates bullet objects (instances of a class) but which of course I want to be completely deleted when they leave the screen, to free up the memory.
I’m monitoring the memory, but I’m clearly not destroying each bullet entirely because in the following scene file the memory just trickles up indefinitely. I’m doing my best to destroy the display object, the physics object, and all transitions associated with the object, in the checkEverything function but the memory still trickles up. Not very fast, but I can’t tell if this is to be expected or not?
If you’re wondering about where my class code comes from I’m shamelessly nicking it from Codea since that’s what I’m used to!
Is there anything else I should be doing? Or is there a more “Corona”-y way to achieve the same result that I’m missing?
https://bitbucket.org/TwoLivesLeft/core/wiki/CodeaClasses
[lua]
– level1.lua
local composer = require( “composer” )
local scene = composer.newScene()
local physics = require “physics”
physics.start(); physics.pause()
– forward declarations and other locals
local screenW, screenH, halfW = display.contentWidth, display.contentHeight, display.contentWidth*0.5
local fireState = false
local bullets = {}
local Bullet
local class = function(base)
local c = {} – a new class instance
if type(base) == ‘table’ then
– our new class is a shallow copy of the base class!
for i,v in pairs(base) do
c[i] = v
end
c._base = base
end
– the class will be the metatable for all its objects,
– and they will look up their methods in it.
c.__index = c
– expose a constructor which can be called by <classname>(<args>)
local mt = {}
mt.__call = function(class_tbl, …)
local obj = {}
setmetatable(obj,c)
if class_tbl.init then
class_tbl.init(obj,…)
else
– make sure that any stuff from the base class is initialized!
if base and base.init then
base.init(obj, …)
end
end
return obj
end
c.is_a = function(self, klass)
local m = getmetatable(self)
while m do
if m == klass then return true end
m = m._base
end
return false
end
setmetatable(c, mt)
return c
end
local function fireCannon()
table.insert(bullets, Bullet())
end
local function checkEverything()
for i = #bullets, 1, -1 do
if bullets[i]:checkPos() then
physics.removeBody(bullets[i].ellipse)
bullets[i].ellipse:removeSelf()
transition.cancel(bullets[i].ellipse)
bullets[i].ellipse = nil
table.remove(bullets, i)
end
end
collectgarbage()
end
function scene:create( event )
– 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.
local sceneGroup = self.view
– create a grey rectangle as the backdrop
local background = display.newRect( 0, 0, screenW, screenH )
background.anchorX = 0
background.anchorY = 0
background:setFillColor( 0 )
sceneGroup:insert( background )
timer.performWithDelay( 100, fireCannon , -1 )
timer.performWithDelay(1000, checkEverything, -1)
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 and is about to move on screen
elseif phase == “did” then
physics.start()
end
end
function scene:hide( event )
local sceneGroup = self.view
local phase = event.phase
if event.phase == “will” then
– Called when the scene is on screen and is about to move off screen
–
– INSERT code here to pause the scene
– e.g. stop timers, stop animation, unload sounds, etc.)
physics.stop()
elseif phase == “did” then
– Called when the scene is now off screen
end
end
function scene:destroy( event )
– 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.
local sceneGroup = self.view
package.loaded[physics] = nil
physics = nil
end
Bullet = class()
function Bullet:init()
self.ellipse = display.newCircle( display.contentWidth/2, display.contentHeight - 250, 10 )
self.ellipse.stroke = {1,1,1}
self.ellipse.strokeWidth = 1
self.ellipse.fill = {1,0,0}
transition.to(self.ellipse, {time = 1000, y = -100})
physics.addBody( self.ellipse, “static”, { radius=10, density = 0} )
end
function Bullet:checkPos()
if self.ellipse.x < -100 or (self.ellipse.x > (display.contentWidth + 100)) or
self.ellipse.y < -100 or (self.ellipse.y > (display.contentWidth + 100)) then
return true
end
return false
end
local monitorMem = function()
collectgarbage()
print( "MemUsage: " … collectgarbage(“count”) )
local textMem = system.getInfo( “textureMemoryUsed” ) / 1000000
print( "TexMem: " … textMem )
end
Runtime:addEventListener( “enterFrame”, monitorMem )
– Listener setup
scene:addEventListener( “create”, scene )
scene:addEventListener( “show”, scene )
scene:addEventListener( “hide”, scene )
scene:addEventListener( “destroy”, scene )
return scene
[/lua]