Destroying bodies

If I am creating multiple physics bodies using a class then how can I destroy a body as soon as a new body is created.
I know this is similar to a question I had asked before but I can’t figure out how to destroy the previous body. If I destroy the previous body the new one is also destroyed while being created and codea crashes
Here’s the code


--# Main
function setup()
    body = {}
    parameter.watch("#body")
end
    
function draw()
    background(255, 255, 255, 255)
    if createBody then
        b:draw()
    end
    if #body>1 then
        b.bodies.destroy()
    end
end

function touched(touch)
    tx = touch.x
    ty = touch.y
    if touch.state == BEGAN then
        b = Bodies()
        createBody = true
    end
end
--# Bodies
Bodies = class()

function Bodies:init()
    self.bodies = physics.body(CIRCLE,10)
    self.bodies.x = tx
    self.bodies.y = ty
    self.bodies.linearVelocity = vec2(-100,0)
    self.bodies.gravityScale = 0
    table.insert(body,self.bodies)
end

function Bodies:draw()
    pushStyle()
    fill(255, 0, 0, 255)
    ellipse(self.bodies.x,self.bodies.y,20)
    popStyle()
end

Post just enough code to show the problem, please

Generally, you destroy the physics object, then set it to nil, but never do this in the collide function, or it will crash

Added the code

It should be b.bodies:destroy(), ie with a colon

You might also want to add b=nil, to destroy all the other info as well

Nope it gives an error stating attempt to index global b (a nil value) on line 9 I.e b:draw().
Is there any way I can number every body I create giving it a unique identity?

Try this

function draw()
    background(255, 255, 255, 255)
    if b then  b:draw() end
end

function touched(touch)
    tx = touch.x
    ty = touch.y
    if touch.state == BEGAN then
       if b then b.bodies:destroy() end
        b = Bodies()
    end
end

Thanks it worked I checked out using collide function making sound like this


--# Main
function setup()
    body = {}
    parameter.watch("#body")
    w = physics.body(EDGE, vec2(0,0),vec2(0,HEIGHT))
end

function draw()
    background(255, 255, 255, 255)
    if b then
        b:draw()
    end
end

function touched(touch)
    tx = touch.x
    ty = touch.y
    if touch.state == BEGAN then
        if b then b.bodies:destroy() end
        b = Bodies()
    end
end

function collide(contact)
    if contact.state == BEGAN then
        sound(SOUND_POWERUP, 41573)
    end
end
--# Bodies
Bodies = class()

function Bodies:init()
    self.bodies = physics.body(CIRCLE,10)
    self.bodies.x = tx
    self.bodies.y = ty
    self.bodies.linearVelocity = vec2(-100,0)
    self.bodies.gravityScale = 0
    table.insert(body,self.bodies)
end

function Bodies:draw()
    pushStyle()
    fill(255, 0, 0, 255)
    ellipse(self.bodies.x,self.bodies.y,20)
    popStyle()
end

Can you please explain what you did out there. Did you destroy the body if there was another body b or was it something else?

I simply deleted the existing one before creating a new one, so no need for a table

. @Saurabh I noticed you had a table for body, but you weren’t using it. I modified you code a little to use the table, so you can now draw multiple bodies. I also added code to destroy the body and remove them from the body table when it collides with the EDGE.


--# Main
function setup()
    body = {}
    parameter.watch("#body")
    w = physics.body(EDGE, vec2(0,0),vec2(0,HEIGHT))
end

function draw()
    background(255, 255, 255, 255)
    for x,y in pairs(body) do
        if y.bodies.dest then    -- if true then
            y.bodies:destroy()    -- destroy body
            table.remove(body,x)    -- remove body from table
        else
            y:draw()    -- draw body
        end
    end
end

function touched(touch)
    if touch.state == BEGAN then
        table.insert(body,Bodies(touch.x,touch.y))
    end
end

function collide(contact)
    if contact.state == BEGAN then
        sound(SOUND_POWERUP, 41573)
        contact.bodyB.dest=true    -- set destroy to true
    end
end

--# Bodies
Bodies = class()

function Bodies:init(x,y)
    self.bodies = physics.body(CIRCLE,10)
    self.bodies.x = x
    self.bodies.y = y
    self.bodies.linearVelocity = vec2(-100,0)
    self.bodies.gravityScale = 0
    self.bodies.dest=false    -- used to destroy body 
end

function Bodies:draw()
    pushStyle()
    fill(255, 0, 0, 255)
    ellipse(self.bodies.x,self.bodies.y,20)
    popStyle()
end

Thanks @dave1707!! Now I have landed into another weird problem if I use this code


--# Main
function setup()
    purple = color(162, 0, 255, 255)
    brown = color(119, 74, 30, 255)
    b = physics.body(CIRCLE,10)
    b.linearVelocity = vec2(100,0)
    b.x = WIDTH/4
    b.y = HEIGHT/2
    b.gravityScale = 0
end

function draw()
    background(255, 255, 255, 255)
    CreatePortal(WIDTH/2,HEIGHT/2,purple)
    fill(255, 190, 0, 255)
    ellipse(b.x,b.y,20)
end

function collide(contact)
    if contact.state == BEGAN then 
     sound(SOUND_JUMP, 31846)
    end
end

function CreatePortal(x,y,colour)
    portal = physics.body(EDGE, vec2(x, y - 25), vec2(x, y + 25))
    portal.sensor = true
    pushStyle()
    fill(colour)
    ellipse(x, y, 10, 100)
    popStyle()
end

Codea crashes during the collision but if I create ‘portal’ in setup like so


--# Main
function setup()
    p = physics.body(EDGE,vec2(WIDTH/2,HEIGHT/2-50), vec2(WIDTH/2,HEIGHT/2+50))
    p.sensor = true
    b = physics.body(CIRCLE,10)
    b.linearVelocity = vec2(100,0)
    b.x = WIDTH/4
    b.y = HEIGHT/2
    b.gravityScale = 0
end

function draw()
    background(255, 255, 255, 255)
    fill(255, 190, 0, 255)
    ellipse(b.x,b.y,20)
    ellipse(WIDTH/2,HEIGHT/2,10,100)
end

function collide(contact)
    if contact.state == BEGAN then 
        sound(SOUND_JUMP, 31852)
    end
end

Then codea doesn’t crash. What mistake am I making in CreatePortal() function?

The first one wasn’t crashing for me. The collision BEGAN seems to be called a lot (I added a print statement and saw multiple calls) instead of just once which may be the cause of your crash. I added a variable to control it. See if this works better for you.

EDIT: I just realized you’re calling CreatePortal every time you call draw. That’s the problem. CreatePortal should be called once in setup.

EDIT: Here is the corrected version.


--# Main
function setup()
    purple = color(162, 0, 255, 255)
    brown = color(119, 74, 30, 255)
    b = physics.body(CIRCLE,10)
    b.linearVelocity = vec2(100,0)
    b.x = WIDTH/4
    b.y = HEIGHT/2
    b.gravityScale = 0
    CreatePortal(WIDTH/2,HEIGHT/2,purple)
end

function draw()
    background(255, 255, 255, 255)
    fill(portal.colour)
    ellipse(portal.x1, portal.y1, 10, 100)
    fill(255, 190, 0, 255)
    ellipse(b.x,b.y,30)
end

function collide(contact)
    if contact.state == BEGAN then 
        sound(SOUND_JUMP, 31846)
    end
end

function CreatePortal(x,y,colour)
    portal = physics.body(EDGE, vec2(x, y - 25), vec2(x, y + 25))
    portal.x1=x
    portal.y1=y
    portal.colour=colour
    portal.sensor = true
end

Thanks!! @dave1707 it’s working fine now.