Trouble removing collision eventListeners and getting "clean() function" error Director 1.4

Hello there,

I have been pulling my hair out for the past few days trying to figure out how to properly remove collision event listener.
All I have is a few objects falling from the sky (I have a few spawn functions). The problem arrives when I want to go to a different screen (director:changeScene(“scene2”, “crossfade”), and all of a sudden, I am still able to go to the intended scene, but I still see the objects falling from the sky. Clearly, I am not “cleaning up” all of the collision, runtime listeners on my previous screen. Please Help!
On the same note, I manages to get a few clouds to “translate” on the background (moving from right to left), but again, I hit the same problem: - once I try to leave to a different scene, onButtonClick, I get error about is trying to upvalue x but then x is nil or something… as you can see, I am very frustrating. And I am using Director class 1.4.

Here’s my code just to put things into perspective. Your help is highly apprecited! Thank you in advance

[code]
new = function ()

display.setStatusBar(display.HiddenStatusBar);

– Imports, Include any external references that this scenes needs
– Example: local ui = require ( “ui” )

local ui = require(“ui”)
local physics = require(“physics”)
local easingx = require(“easing”)
physics.start()
physics.setGravity(0, 1)
–physics.setDrawMode(“hybrid”)
local sprite = require(“sprite”)


– SCORE –

score = require(“score”)

– offset for the placard
local border = 5

– get information about the score placard
local scoreInfo = score.getInfo()


– Handle any Params that get passed to the Scene

local vLabel = “”
local vReload = false

if type( params ) == “table” then

if type( params.label ) == “string” then
vLabel = params.label
end

if type( params.reload ) == “boolean” then
vReload = params.reload
end

end

– Groups

local localGroup = display.newGroup()
local floorGroup = display.newGroup ( )
local fallingGroup = display.newGroup ( )


– Local Variable Definitions

local _W = display.contentWidth
local _H = display.contentHeight
local canHit = {“peach”,“mango”,“grapes”, “bananas”, “floor”, “barrel”,“apple”, “cherries”, “ants”}
local invisible_floor;
local mango_fruit
local banana_fruit
local barrel
local ants
local apples
local cherries
local timerSpawnApples
local timerSpawnCherries
local timerSpawnMangos
local timerSpawnBananas
local timerSpawnAnts
local lives = 3
local baseline = 223
local cloud1
local cloud2
local cloud3
local tPrevious = system.getTimer ( )
local pause_button
local menu_button

tapSound = audio.loadSound ( “button_sound.wav”)

local playTapSound = function()
audio.play(tapSound)
end

– initialize the score placard’s location
score.init( {
x = _W*0.5 + 150,
y = 5 }
)


– Functions

–clouds
cloud1 = display.newImageRect(“cloud01.png”, 100, 50)
cloud2 = display.newImageRect(“cloud02.png”, 100, 50)
cloud3 = display.newImageRect(“cloud03.png”, 120, 40)

local function animateClouds( event )
local tDelta = event.time - tPrevious
tPrevious = event.time

local xOffset = ( 0.01 * tDelta)
cloud1.x = cloud1.x - xOffset
cloud2.x = cloud2.x - xOffset
cloud3.x = cloud3.x - xOffset

if ( cloud1. x + cloud1.contentWidth) < 0 then
cloud1:translate(400 * 2, 0)
end

if ( cloud2.x + cloud2.contentWidth) < 0 then
cloud2:translate(400 * 2, 0)

end

if ( cloud3.x + cloud3.contentWidth) < 0 then
cloud3:translate(320 * 2, 0)
end
end
– Runtime:addEventListener(“enterFrame”, animateClouds)

local startDrag = function( event )
local t = event.target
local phase = event.phase

if “began” == phase then
display.getCurrentStage ( ):setFocus( t )
t.isFocus = true

–store initial position
t.x0 = event.x - t.x
t.y0 = event.y - t.y

–make body temp. kinematic to avoid gravity
event.target.bodyType = “kinematic”

–stop current motion
event.target:setLinearVelocity( 0, 0 )
event.target.angularVelocity = 0

elseif t.isFocus then
if “moved” == phase then
t.x = event.x - t.x0
t.y = event.y - t.y0

elseif “ended” == phase or “cancelled” == phase then
display.getCurrentStage():setFocus( nil )
t.isFocus = false

– Switch body type back to “dynamic”, unless we’ve marked this sprite as a platform
if ( not event.target.isPlatform ) then
event.target.bodyType = “dynamic”
end

end
end

– Stop further propagation of touch event!
return true

end

local spawnCherries = function()
cherries = display.newImageRect(“cherries.png”, 40,40)
cherries.x = math.random( 12, 50)
cherries.x = math.random(120, 300)
cherries.y = math.random( -200, -100)
physics.addBody(cherries, {density=1.2, bounce = 0, radius = 5})
cherries.hit = “cherries”

–OnCollision With floor
local function onCherriesCollision(self, event)
if ( event.other.hit == “barrel” ) then
score.setScore( score.getScore() + 25)
playTapSound()
self:removeSelf()
return true
elseif( event.other.hit == “floor”) then

self:removeSelf()
elseif( event.other.hit == “ants”) then
score.setScore( score.getScore() - 10)
self:removeSelf()

end

end
cherries.collision = onCherriesCollision
cherries:addEventListener( “collision” , cherries )
end

local spanwApples = function()
apples = display.newImageRect(“apple.png”, 40,40)
apples.x = math.random( 40, 300)
apples.x = math.random(67, 300)
apples.y = math.random( -200, -100)
physics.addBody(apples, {density=1.2, bounce = 0, radius = 5})
apples.hit = “apple”

–OnCollision With floor
local function onApplesCollision(self, event)
if ( event.other.hit == “barrel” ) then
score.setScore( score.getScore() + 40)
playTapSound()
self:removeSelf()
return true
elseif( event.other.hit == “floor”) then

self:removeSelf()
elseif (event.other.hit == “ants”) then
score.setScore( score.getScore() - 10)
self:removeSelf()
end

end
apples.collision = onApplesCollision
apples:addEventListener( “collision” , apples )

end
local spawnAnts = function()
ants = display.newImageRect(“ant.png”, 40,40)
ants.x = math.random( 23, 100)
ants.x = math.random(50, 300)
ants.y = math.random( -200, -100)
physics.addBody(ants, {density=1.2, bounce = 0, radius = 5})
ants.hit = “ants”

–OnCollision With floor
local function onAntsCollision(self, event)
if ( event.other.hit == “barrel” ) then
–score.setScore( score.getScore() - 10)
playTapSound()
self:removeSelf()

return true
elseif( event.other.hit ==“floor”) then

self:removeSelf()
elseif( event.other.hit == “ants”) then
score.setScore( score.getScore() - 10)
self:removeSelf()

end

end
ants.collision = onAntsCollision
ants:addEventListener( “collision” , ants )

end
local spawnMangos = function()
mango_fruit = display.newImageRect(“mango.png”, 35,35)
mango_fruit.x = math.random( 40, 190)
mango_fruit.x = math.random(29, 300)
mango_fruit.y = math.random( -200, -100)
physics.addBody(mango_fruit, {density=1.2, bounce = 0, radius = 5})
mango_fruit.hit = “mango”

–OnCollision With floor
local function onMangosCollision(self, event)
if ( event.other.hit == “barrel” ) then
score.setScore( score.getScore() + 30)
playTapSound()
self:removeSelf()
return true
elseif(event.other.hit ==“floor”) then

self:removeSelf()
elseif( event.other.hit == “ants”) then
score.setScore( score.getScore() - 10)
self:removeSelf()
end

end
mango_fruit.collision = onMangosCollision
mango_fruit:addEventListener( “collision” , mango_fruit )

end

local spawnBananas = function()
banana_fruit = display.newImageRect(“bananas.png”, 40,40)
banana_fruit.x = math.random( 10, 220)
banana_fruit.x = math.random(50, 350)
banana_fruit.y = math.random( -200, -100)
physics.addBody(banana_fruit, {density=1.2, bounce = 0, radius = 5})
banana_fruit.hit = “bananas”

–OnCollision With floor
local function onBananasCollision(self, event)
if ( event.other.hit == “barrel” ) then
score.setScore( score.getScore() + 20)
playTapSound()
self:removeSelf()

return true
elseif ( event.other.hit == “floor”) then
self:removeSelf()

elseif ( event.other.hit == “ants”) then
score.setScore( score.getScore() - 10)
self:removeSelf()
end

end
banana_fruit.collision = onBananasCollision
banana_fruit:addEventListener( “collision” , banana_fruit )

end

------REMOVE TIMERS ----
local removeTimers = function()
print("Calling removeTimers() ")
timer.cancel ( timerSpawnMangos )
timer.cancel(timerSpawnBananas)
timer.cancel(timerSpawnAnts)
timer.cancel(timerSpawnApples)
timer.cancel(timerSpawnCherries)
end
–ONCLICK BUTTON EVENTS
local onMenuButton = function( event )

if ( event.phase ==“release” and menu_button.isActive) then
– removeTimers()
Runtime:removeEventListener(“enterFrame”, animateClouds)

– score.setScore( 0)
director:changeScene(“mainMenu”, “crossfade”)
end

end


–UI OBJECTS

pause_button = ui.newButton{
defaultSrc = “pausebtn.png”,
defaultX = 37,
defaultY = 37,
overSrc = “pausebtn-over.png”,
overX = 34,
overY = 34,
onEvent = onPauseButton,
id = “pause_button”,
text = “”,
font = “Verdana”,
textColor = { 255, 255, 255, 255 },
size = 16,
emboss = false
}
menu_button = ui.newButton{
defaultSrc = “pausemenubtn.png”,
defaultX = 37,
defaultY = 37,
overSrc = “pausemenubtn-over.png”,
overX = 34,
overY = 34,
onEvent = onMenuButton,
id = “menu_button”,
text = “”,
font = “Verdana”,
textColor = { 255, 255, 255, 255 },
size = 16,
emboss = false

}

–Change Scene-----

local moveToScene = function(event)

–Example scene change with parameters
–director:changeScene( { label=“Scene Reloaded” }, “screen2”,“moveFromRight” )

–Example scene change without parameters
–director:changeScene( “screen1”, “crossfade” )
end


– Code here

local background_image = display.newImageRect(“game_bg.png”, 480, 320)
invisible_floor = display.newImageRect(“invisible_floor.png”, 980, 1)
barrel = display.newImageRect(“barrel64.png”, 64, 64)

–====================================================================–
– INITIALIZE, Every Display Object must get shoved into the local Display Group
– Example: localGroup:insert( background )
–====================================================================–
local initVars = function ()
localGroup:insert(background_image)
localGroup:insert(cloud1)
localGroup:insert(cloud2)
localGroup:insert(cloud3)
floorGroup:insert(invisible_floor)
floorGroup:insert(barrel)
floorGroup:insert(pause_button)
floorGroup:insert(menu_button)

–DECLARATIONS

—POSITIONING
background_image.x = _W*0.5
background_image.y = _H*0.5

cloud1.x = 240; cloud1.y = 160
cloud2.x = 720; cloud2.y = 160
cloud3.x = 1200; cloud3.y = 160

invisible_floor.x = _W;
invisible_floor.y = _H;
physics.addBody ( invisible_floor, “static”, {bounce=0} )
invisible_floor.hit = “floor”

barrel.x = invisible_floor.x * .5
barrel.y =invisible_floor.y -35
physics.addBody( barrel, { density=1.0})
barrel.hit = “barrel”

pause_button.x = _W * 0.5 - 200
pause_button.y = _H * 0.5 -120

menu_button.x = _W*0.5 - 145
menu_button.y = _H*0.5 - 120

–LISTENERS–
timerSpawnMangos = timer.performWithDelay ( 5600, spawnMangos, 0 )
timerSpawnBananas = timer.performWithDelay(4900, spawnBananas, 0)
timerSpawnAnts = timer.performWithDelay(5600, spawnAnts, 0)
timerSpawnApples = timer.performWithDelay(4500, spawnApples, 0)
timerSpawnCherries = timer.performWithDelay(7800, spawnCherries, 0)
barrel:addEventListener(“touch”, startDrag )
Runtime:addEventListener(“enterFrame”, animateClouds)

print(“Initiate variables done!”)
end

–Clean up local variables, etc…
clean = function()
print(“Cleaning up stuff!”)
cherries:removeEventListener(“collision”, cherries)
banana_fruit:removeEventListener(“collision”, banana_fruit)
mango_fruit:removeEventListener(“collision”, mango_fruit)
ants:removeEventListener(“collision”, ants)
apples:removeEventListener(“collision”, apples)
barrel:removeEventListener(“touch”, startDrag)
–removeTimers()
display.remove(background_image);
background_image = nil
print(“Memory Cleaned!”)

end

– INITIALIZE variables

initVars()


– MUST return a display.newGroup()

return localGroup

end

[/code] [import]uid: 75258 topic_id: 17747 reply_id: 317747[/import]

I figured it out! Basically all I had to do was to comment to get rid of collision eventlisteners, and made sure to cancel all timers (used to spawn the falling objects) upon cancel ( inside the onCancelButton) !!

I hope this helps some other person with the same problem in the future.

:slight_smile: [import]uid: 75258 topic_id: 17747 reply_id: 68111[/import]