finalize event happens when ?

When an object have a transition during he is removed, the transition continue :

I always build a delete function to my object to manage the project, because the finalize event is not called at the good time.

local r=display.newRect(0,0,100,100) r.delete=function() if r then if r.tr then transition.cancel(r.tr) ; r.tr=nil end r:removeSelf() // error here because r.removeSelf is nil, so no function can be called r=nil end end r.tr=transition.to(r,{time=10000,x=200,onComplete=r.delete}) timer.performWithDelay(5000,function() r:removeSelf() end)

Because of the excecution delay during a frame, I prefere delete the object immediately during the calculus process, not in the end of the frame.

local tableOfObjects = {} local r=display.newRect(0,0,100,100) ; tableOfObjects[r]=r // this reference in tableOfObjects will be managed too r.enterFrame=function() end //all my actions r.tr=transition.to(r,{time=2000,x=200,onComplete=r.delete}) // I use delete function at the end just to try if no bug arrived r:addEventListener( "anEvent", r ) // touch, collision, etc... Runtime:addEventListener("enterFrame",r) //I remove properly the actions here r.manageDelete=function() tableOfObjects[r]=nil if r.tr then transition.cancel( r.tr ) ; r.tr=nil end r:removeEventListener( "finalize", r ) r:removeEventListener( "anEvent", r ) Runtime:removeEventListener( "enterFrame", r ) end //this function delete the object immediately r.delete=function(fromFinalize) if not r.isDeleted then r.manageDelete() r.isDeleted=true if not fromFinalize then r:removeSelf() end // if I call the delete function with the removeSelf method, I don't removed twice end end function r:finalize(event) r.delete(true) r=nil end r:addEventListener( "finalize", r ) timer.performWithDelay(1000,function() r:removeSelf() end)

That’s look " a lot " but it is better like this : manage all the cancellation and removeEvent in one side, and then remove the object.

(_ Sorry about the vertical spacing of this post;  I’m having trouble with the formatting. _)

  1. In my experience this is not true. 

When an object have a transition during he is removed, the transition continue

 
Deleting display objects ends the transitions associated with that object. 
 
_ test1.lua _  in the example zip file I provided demonstrates this clearly.
 
 
 
2. You can easily cancel all transitions associated with a display object like this:

local obj = display.newCircle( ... ) transitions.to( obj, ... ) -- add a trantision to obj transitions.to( obj, ... ) -- add another trantision to obj transition.cancel( obj ) -- cancels both transitions
  1. If you want to remove a display object when a transition completes, just use display.remove

    transition.to( obj, { x = 100, onComplete = display.remove } )

  2. I’m not sure what this meant:
     

if I call the delete function with the removeSelf method, I don’t removed twice

However, if you’re saying you have issues with duplicate deletes, that is part of why I encourage all users to use display.remove() instead of obj:removeSelf()

Calling display.remove() twice is safe and has no negative side-effects.  Calling obj:removeSelf() twice will crash your game/app.

On the flip side, getting that crash tells you you’ve got a problem with your design.

  1. Your addEventListner() calls are all redundantly coded.

If you direclty attach a function to the object using the same name as the event, this is how you should write your code:

local obj = display.new... function obj.collision()( self, event ) ... end obj:addEventListener( "collision" ) -- DO NOT PASS ARG 2; It is implied that 'obj' has the function

However, if you are using a standalone function you do this:

local obj = display.new... local function collision( self, event ) ... end obj:addEventListener( "collision", collision )

It sounds from this discussion that what you really need to do is add some simple gating flags to your code instead of trying to bend over backwards to hijack the sequence in which things occurs.

This is an example of a gating flag:

local obj1 = display.new??? local obj2 = display.new??? -- Assume I added bodies to obj1 and obj2 local function onCollision( self, event ) local other = event.other if( self.dead ) then return false end if( not other.dead ) then other:setFillColor( 1, 0, 1 ) end self.dead = true display.remove( self ) return false end obj1.collision = onCollision obj2.collision = onCollision obj1:addEventListener( "collision" ) obj2:addEventListener( "collision" )

In this example, both obj1 and obj2 use the same code as their collision listener (saves memory), and in each case, the listeners are gated by the flag ‘dead’.

  • If ‘dead’ is true, the collision listener exits early.
  • On the very first collision event for obj1 and obj2, the respective object referred to ‘self’ is deleted and marked as ‘dead’
  • The ‘other’ object is then set to pink.

Note: In the case where obj1 and obj2 collide with each other, one will be deleted before the other.  So, if we  didn’t have this code around the setFillColor() call, we could get an error.

 if( not other.dead ) then ... end

The ‘dead’ flag is immediately visible and available to all code referencing the object immediately after the flag is set.  Thus, you can use it to gate critical events and execution if you can’t wait one frame for the normal cleanup mechanisms to kick in.

Note2:  Notice I don’t use a finalize function and I don’t remove the ‘collision’ event listener.  I don’t have to because it is removed automatically by the process of deleting the display object.

Only Runtime event listeners need to be manually removed when deleting a display object.

As usual excellent explanation @roaminggamer

Only one thing. I thought that to eliminate a body in the collision it was necessary to use a small timer.

https://docs.coronalabs.com/api/event/collision/index.html#gotchas

So I thought you forgot it in a hurry

I was about to report it here but I did a test and this did not give any problems.

My question is: better to use timer or is there anything I’m forgetting?

@maximo97,

If you need to manipulate the physics body of any objects (as a result of a collision) including the owner of the listener, you must do so after a short delay (i.e. using a timer.*).

Destroying the display object does not need to be delayed.

Destroying a display object with a body causes the object and body to be destroyed at the end of the frame.

ok thanks for that tips. I had suspicious about display.remove because we don’t know what is inside. That’s why I use removeSelf + nil duo.

local obj = display.new... function obj.collision()( self, event ) ... end obj:addEventListener( "collision" ) -- DO NOT PASS ARG 2; It is implied that 'obj' has the function

Don’t use capital letters please, it’s like screaming on someone lol.

 

I remember a note talking about this missing. They talked about error that can be involved due to future updates of the inner code, that can cause fatal error.

And in the official docs, they says to pass a second variable in any cases.

local obj = display.new... local function collision( self, event ) ... end obj:addEventListener( "collision", collision )

In my example I have variable in my object’s creator classes. So I need to build an obj:method function for each objects to scope variables.

thanks

re: 

Don't use capital letters please, it's like screaming on someone lol.

I use CAPS in code posts because there is no way to highlight the code comments.  i.e. There is no bold  to draw your attention to the comment.