Runtime Error removing objects (short interval)

Hello!

The help last time was really quick and useful, so I will try again:)

I´m dropping different objects from top to bottom and the player must catch them with characters tongue. If they hit ground they should be removed (simplified explanation).

Now the problem is that if the objects are falling with a very short interval and hit the ground, I get a runtime error:

WARNING: Attempting to set property(x) with nil WARNING: Attempting to set property(y) with nil Runtime error ..\level3.lua:27: attempt to index field 'parent' (a nil value) stack traceback: [C]: ? ...level3.lua:27: in function '\_listener' ?: in function <?:514ground hit<br>

If the interval is longer, for example there is a one or two second cap between the ground collisions, no error is displayed and all works fine. Also there is no error if I don´t remove the object (line 27 in here).

[lua]–***************************************************
– BEE CREATION, COLLISION & DROP
–***************************************************

local onbeeCollision = function( self, event )

if (event.other.myName == “tongue” and event.target.myName == “bee” or event.other.myName == “ground”) then
local doCollision = function()
audio.play( bugCaughtSound )
self.isHit = true
print( “bee destroyed!”)
self.isVisible = false
self.isBodyActive = false

eatenBug.x = self.x; eatenBug.y = self.y
eatenBug.alpha = 0
eatenBug.isVisible = true

local fadebug = function()
transition.to( eatenBug, { time=500, alpha=0 } )
end

transition.to( eatenBug, { time=50, alpha=1.0, onComplete=fadebug } )
timer.performWithDelay( 50, resetTongue )

self.parent:remove( self )
self = nil

end

–COLLISION TIMER
local collisionTimer = timer.performWithDelay( 1, doCollision, 1 )

if event.other.myName == “character” then
bugCount = bugCount + 1
bugText.text = "Catched: " … tostring( bugCount )
bugText.xScale = 0.5; bugText.yScale = 0.5
bugText.x = (480 - (bugText.contentWidth * 0.5)) - 15
bugText.y = 305
print(“bee caught”)

local newScore = gameScore + 2
setScore( newScore )
elseif event.other.myName == “tongue” then
bugCount = bugCount + 1
bugText.text = "Caught: " … tostring( bugCount )
bugText.xScale = 0.5; bugText.yScale = 0.5
bugText.x = (480 - (bugText.contentWidth * 0.5)) - 15
bugText.y = 305
print(“bee caught”)

local newScore = gameScore + 2
setScore( newScore )

elseif event.other.myName == “ground” then
print(“Ground hit!”)
end

end
end

–BEE DROP
local beeDrop = function()
local displayScale = display.contentScaleX

if displayScale < 1 then
beeSheet = sprite.newSpriteSheet( “images/beeSprite@2x.png”, 130, 120 )
else
beeSheet = sprite.newSpriteSheet( “images/beeSprite.png”, 65, 60 )
end

local spriteSet1 = sprite.newSpriteSet(beeSheet, 1, 2)
sprite.add( spriteSet1, “move”, 1, 2, 100, 0 )
bee = sprite.newSprite( spriteSet1 )

if displayScale < 1 then
bee.xScale = .5; bee.yScale = .5
end

bee.x = display.contentWidth / 2
bee.y = display.contentHeight / 2
bee:prepare(“move”)
bee:play()

bee.x = mRand( 80, 450 ); bee.y = -40
transition.to( bee, { time=mRand(1500, 2000), y = 400, transition=easing.linear } )
bee.isHit = false

physics.addBody( bee, “dynamic”,{ density=beeDensity, bounce=0, friction=0.5, shape=bugShape } )
bee.isFixedRotation = true
bee.myName = “bee”
gameGroup:insert( bee )

bee.postCollision = onbeeCollision
bee:addEventListener( “postCollision”, bee )
counter:toFront()
pauseBtn:toFront()
scoreText:toFront()
bugText:toFront()
end

– CREATE NEW BEE
local beeTimer = function()
startDrop = timer.performWithDelay( mRand(1000, 1500), beeDrop, 0 )
end[/lua]

So maybe someone has an idea?

Thanks in advance!

Gert [import]uid: 105289 topic_id: 30429 reply_id: 330429[/import]

It seems to be happening only if I have more then one set on items/characters. For example if I remove dropping clocks and leave only the bees, no error is displayed.

The clock part:

[lua]–***************************************************
– CLOCK CREATION, COLLISION & DROP
–***************************************************

local onclockObjectCollision = function( self, event )

if (event.other.myName == “tongue” and event.target.myName == “clockObject” or event.other.myName == “ground”) then
local doCollision = function()
audio.play( bugCaughtSound )
self.isHit = true
print( “clockobject caught”)
self.isVisible = false
self.isBodyActive = false

eatenBug.x = self.x; eatenBug.y = self.y
eatenBug.alpha = 0
eatenBug.isVisible = true

local fadebug = function()
transition.to( eatenBug, { time=500, alpha=0 } )
end

transition.to( eatenBug, { time=50, alpha=1.0, onComplete=fadebug } )
if event.other.myName ~= “ground” then
timer.performWithDelay( 50, resetTongue )
end

self.parent:remove( self )
self = nil

end

–COLLISION TIMER
local collisionTimer = timer.performWithDelay( 1, doCollision, 1 )

if event.other.myName == “character” then
print(“clockObject caught”)
local newScore = gameScore + 0
setScore( newScore )
elseif event.other.myName == “tongue” then
print(“clockObject caught”)
numSeconds = numSeconds + 10
local newScore = gameScore + 0
setScore( newScore )

elseif event.other.myName == “ground” then
print(“ground hit”)
end

end
end

–CLOCK DROP
local clockObjectDrop = function()

local clockObject = display.newImageRect( “images/clock.png”, 30, 30 )

clockObject.x = mRand( 300, 400 ); clockObject.y = -40
transition.to( clockObject, { time=1000, y = 340, transition=easing.linear } )
clockObject.isHit = false

physics.addBody( clockObject, “dynamic”,{ density=clockObjectDensity, bounce=0, friction=0.5, shape=clockObjectShape } )
clockObject.isFixedRotation = true
clockObject.myName = “clockObject”
gameGroup:insert( clockObject )

clockObject.postCollision = onclockObjectCollision
clockObject:addEventListener( “postCollision”, clockObject )
counter:toFront()
pauseBtn:toFront()
scoreText:toFront()
bugText:toFront()

end

– CREATE NEW CLOCK
local clockObjectTimer = function()
startDropClock = timer.performWithDelay( 15000, clockObjectDrop, 0 )
end [/lua]

[import]uid: 105289 topic_id: 30429 reply_id: 122421[/import]

Aren’t you calling it twice?

if (event.other.myName == “tongue” and event.target.myName == “clockObject” or event.other.myName == “ground”)

and

if (event.other.myName == “tongue” and event.target.myName == “bee” or event.other.myName == “ground”)
if it’s: event.other.myName it’s a tongue and the other is ground?

You can see what happend if you call two times a bee or a clock:
bee.x = 10; bee.y = -40
and call at the same time:
startDrop = timer.performWithDelay( 1, beeDrop, 1 )
startDrop = timer.performWithDelay( 1, beeDrop, 1 )

The error is like you are trying to delete something inexistant.

Did i understand the question? [import]uid: 116842 topic_id: 30429 reply_id: 122479[/import]

Thanks for the fast reply.

I don´t fully follow you, sorry (I actually understand what you are saying but can´t figure a solution).
should I leave it like:
[lua]if (event.other.myName == “tongue” and event.target.myName == “bee”)[/lua]

And make the ground collision somewhere else? [import]uid: 105289 topic_id: 30429 reply_id: 122591[/import]

Yes, that could be one answer for yourself :slight_smile:

But you can try what i said:

You can see what happend if you call two times a bee or a clock:
bee.x = 10; bee.y = -40
and call at the same time:
startDrop = timer.performWithDelay( 1, beeDrop, 1 )
startDrop = timer.performWithDelay( 1, beeDrop, 1 )

If with just bees and that code it goes wrong, the problem is what i’m saying.

I’m still thinking the problem it’s the if statement:

if (event.other.myName == “tongue” and event.target.myName == “clockObject” or event.other.myName == “ground”)

You can try:
if ( event.target.myName == “clockObject” and event.other.myName == “ground” or event.other.myName == “tongue” )

I imagine that with this, it solves the problem ( do the same with bees )

You can try your own answer before mine, btw.

Other thing:
If i didn’t understand badly, if the listener of the collision of bees is onbeecollision, event.target.myName will be always “bee”. [import]uid: 116842 topic_id: 30429 reply_id: 122600[/import]

Same thing with every way…
It only works great if I don´t remove the objects in:
[lua]–self.parent:remove( self )
–self = nil[/lua]

On the other the ground is not that relevant, I could remove it, I use it only to remove objects, but still would like to know why it happens exactly.
I guess I have messed with it for weeks now…
Sometimes the whole level can be played out (45+ seconds) without any runtime errors described above, but sometimes a few happen. [import]uid: 105289 topic_id: 30429 reply_id: 122706[/import]

One more question, is the removing actually relevant in this case?

When I use:

[lua]local function monitorMem(event)
collectgarbage(“collect”)
print( “\nMemUsage: " … (collectgarbage(“count”)/1000) … " MB”)
print("Texture Usage " … system.getInfo( “textureMemoryUsed” ) / 1000000)
return true
end[/lua]

I can´t see any difference, with or without:

[lua]self.parent:remove( self )
self = nil[/lua]

Thanks (hope it is my final question in this thread)
[import]uid: 105289 topic_id: 30429 reply_id: 122857[/import]

It seems to be happening only if I have more then one set on items/characters. For example if I remove dropping clocks and leave only the bees, no error is displayed.

The clock part:

[lua]–***************************************************
– CLOCK CREATION, COLLISION & DROP
–***************************************************

local onclockObjectCollision = function( self, event )

if (event.other.myName == “tongue” and event.target.myName == “clockObject” or event.other.myName == “ground”) then
local doCollision = function()
audio.play( bugCaughtSound )
self.isHit = true
print( “clockobject caught”)
self.isVisible = false
self.isBodyActive = false

eatenBug.x = self.x; eatenBug.y = self.y
eatenBug.alpha = 0
eatenBug.isVisible = true

local fadebug = function()
transition.to( eatenBug, { time=500, alpha=0 } )
end

transition.to( eatenBug, { time=50, alpha=1.0, onComplete=fadebug } )
if event.other.myName ~= “ground” then
timer.performWithDelay( 50, resetTongue )
end

self.parent:remove( self )
self = nil

end

–COLLISION TIMER
local collisionTimer = timer.performWithDelay( 1, doCollision, 1 )

if event.other.myName == “character” then
print(“clockObject caught”)
local newScore = gameScore + 0
setScore( newScore )
elseif event.other.myName == “tongue” then
print(“clockObject caught”)
numSeconds = numSeconds + 10
local newScore = gameScore + 0
setScore( newScore )

elseif event.other.myName == “ground” then
print(“ground hit”)
end

end
end

–CLOCK DROP
local clockObjectDrop = function()

local clockObject = display.newImageRect( “images/clock.png”, 30, 30 )

clockObject.x = mRand( 300, 400 ); clockObject.y = -40
transition.to( clockObject, { time=1000, y = 340, transition=easing.linear } )
clockObject.isHit = false

physics.addBody( clockObject, “dynamic”,{ density=clockObjectDensity, bounce=0, friction=0.5, shape=clockObjectShape } )
clockObject.isFixedRotation = true
clockObject.myName = “clockObject”
gameGroup:insert( clockObject )

clockObject.postCollision = onclockObjectCollision
clockObject:addEventListener( “postCollision”, clockObject )
counter:toFront()
pauseBtn:toFront()
scoreText:toFront()
bugText:toFront()

end

– CREATE NEW CLOCK
local clockObjectTimer = function()
startDropClock = timer.performWithDelay( 15000, clockObjectDrop, 0 )
end [/lua]

[import]uid: 105289 topic_id: 30429 reply_id: 122421[/import]

Aren’t you calling it twice?

if (event.other.myName == “tongue” and event.target.myName == “clockObject” or event.other.myName == “ground”)

and

if (event.other.myName == “tongue” and event.target.myName == “bee” or event.other.myName == “ground”)
if it’s: event.other.myName it’s a tongue and the other is ground?

You can see what happend if you call two times a bee or a clock:
bee.x = 10; bee.y = -40
and call at the same time:
startDrop = timer.performWithDelay( 1, beeDrop, 1 )
startDrop = timer.performWithDelay( 1, beeDrop, 1 )

The error is like you are trying to delete something inexistant.

Did i understand the question? [import]uid: 116842 topic_id: 30429 reply_id: 122479[/import]

Thanks for the fast reply.

I don´t fully follow you, sorry (I actually understand what you are saying but can´t figure a solution).
should I leave it like:
[lua]if (event.other.myName == “tongue” and event.target.myName == “bee”)[/lua]

And make the ground collision somewhere else? [import]uid: 105289 topic_id: 30429 reply_id: 122591[/import]

Yes, that could be one answer for yourself :slight_smile:

But you can try what i said:

You can see what happend if you call two times a bee or a clock:
bee.x = 10; bee.y = -40
and call at the same time:
startDrop = timer.performWithDelay( 1, beeDrop, 1 )
startDrop = timer.performWithDelay( 1, beeDrop, 1 )

If with just bees and that code it goes wrong, the problem is what i’m saying.

I’m still thinking the problem it’s the if statement:

if (event.other.myName == “tongue” and event.target.myName == “clockObject” or event.other.myName == “ground”)

You can try:
if ( event.target.myName == “clockObject” and event.other.myName == “ground” or event.other.myName == “tongue” )

I imagine that with this, it solves the problem ( do the same with bees )

You can try your own answer before mine, btw.

Other thing:
If i didn’t understand badly, if the listener of the collision of bees is onbeecollision, event.target.myName will be always “bee”. [import]uid: 116842 topic_id: 30429 reply_id: 122600[/import]

Same thing with every way…
It only works great if I don´t remove the objects in:
[lua]–self.parent:remove( self )
–self = nil[/lua]

On the other the ground is not that relevant, I could remove it, I use it only to remove objects, but still would like to know why it happens exactly.
I guess I have messed with it for weeks now…
Sometimes the whole level can be played out (45+ seconds) without any runtime errors described above, but sometimes a few happen. [import]uid: 105289 topic_id: 30429 reply_id: 122706[/import]

One more question, is the removing actually relevant in this case?

When I use:

[lua]local function monitorMem(event)
collectgarbage(“collect”)
print( “\nMemUsage: " … (collectgarbage(“count”)/1000) … " MB”)
print("Texture Usage " … system.getInfo( “textureMemoryUsed” ) / 1000000)
return true
end[/lua]

I can´t see any difference, with or without:

[lua]self.parent:remove( self )
self = nil[/lua]

Thanks (hope it is my final question in this thread)
[import]uid: 105289 topic_id: 30429 reply_id: 122857[/import]