Page 2 of 3

Re: body:destroy()

Posted: Tue Mar 01, 2011 2:28 pm
by tentus
bartbes wrote:Alright, let's just end all this:
For both destroy() and the GC to function, all shapes, contacts and other associated things have to be released as well.
Then, the difference between destroy() and the GC: destroy() is there to force removal at that specific time, the GC may take some longer.
As for the crashes: If you destroy an object that is still colliding Box2D won't like it, which is why moving it outside of the world, or setting it to no longer collide solves this problem.
So, just for clarity:

To destroy a body you also have to destroy the shape beforehand, otherwise it's just pretending to be destroyed, right? And before you do that you should put the body somewhere remote so nothing is colliding with it, or set the mask to every category used.

Re: body:destroy()

Posted: Tue Mar 01, 2011 2:33 pm
by bartbes
I'm not sure about the exact state of the shapes, but the GC won't collect a body when there are still shapes attached to it which haven't been collected, really, the no-collision thing is the most important, because Box2D will try using data which no longer exists otherwise.

Re: body:destroy()

Posted: Tue Mar 01, 2011 8:40 pm
by BlackBulletIV
I've written a little function here, that might work (it's untested).

Paramaters:
obj - A table with a body properties and shapes property which is a table holding all the shapes
worldX - The least x position in the world.
worldY - The least y position in the world.

Code: Select all

function destroyBody(obj, worldX, worldY)
    obj.body:setPosition(worldX - 10000, worldY - 10000)
    
    for _, v in pairs(obj.shapes) do
        v:destroy()
    end
    
    obj.body:destroy()
end

Re: body:destroy()

Posted: Tue Mar 01, 2011 9:06 pm
by tentus
BlackBulletIV wrote:I've written a little function here, that might work (it's untested).

Paramaters:
obj - A table with a body properties and shapes property which is a table holding all the shapes
worldX - The least x position in the world.
worldY - The least y position in the world.

Code: Select all

function destroyBody(obj, worldX, worldY)
    obj.body:setPosition(worldX - 10000, worldY - 10000)
    
    for _, v in pairs(obj.shapes) do
        v:destroy()
    end
    
    obj.body:destroy()
end
Won't that put everything in the same place, potentially causing box2d to collide them?

Re: body:destroy()

Posted: Tue Mar 01, 2011 9:57 pm
by bartbes
Nobody says (x-10000, y-100000) isn't in range, and if it's out of the world it will fail as well, you should probably use Shape:setMask().

Re: body:destroy()

Posted: Tue Mar 01, 2011 10:01 pm
by slime
Yeah, I use setMask and just wait for the GC to pick everything up, in my game.

Re: body:destroy()

Posted: Wed Mar 02, 2011 7:32 am
by BlackBulletIV
tentus wrote:Won't that put everything in the same place, potentially causing box2d to collide them?
Right you are, I didn't think about that.
bartbes wrote:Nobody says (x-10000, y-100000) isn't in range, and if it's out of the world it will fail as well, you should probably use Shape:setMask().
But notice:
BlackBulletIV wrote:worldX - The least x position in the world.
worldY - The least y position in the world.
By least x, y I mean the first two parameters given to love.physics.newWorld. Therefore, it would certainly be out of the way of any other object. But does "if it's out of the world it will fail as well" mean that putting it outside the world isn't doable?

Using setMask() is the way to go, but it requires that a layer is free, so unless the function is given a layer number, it can't assume anything.

EDIT: Oh hang on. Silly me! I see what you're saying with Shape:setMask():

Code: Select all

shape:setMask(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16)
EDIT 2: I've created a function in my PhysicalEntity class (see my Grace framework) which uses the (I think) best method. Tell me if there's something with it.

Code: Select all

function PhysicalEntity:destroy()
    for _, v in ipairs(self.shapes) do
        v:setMask(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16)
        v:destroy()
    end
    
    if self.body then self.body:destroy() end
end

Re: body:destroy()

Posted: Wed Mar 02, 2011 8:48 am
by kikito
I'm wondering if LÖVE should do this automatically (not the releasing of the shapes references; the setMask). I've created an issue.

Re: body:destroy()

Posted: Wed Mar 02, 2011 9:27 am
by BlackBulletIV
That would be... well, LÖVEly. :P

Re: body:destroy()

Posted: Wed Mar 02, 2011 10:17 am
by vrld
I think you still need to wait for one frame before destroying the shapes and body, because they can still be involved in a collision (if you call this function from a collision callback) and box2d will fail.