destroy a physics object when it collides with other ?

General discussion about LÖVE, Lua, game development, puns, and unicorns.
Post Reply
PGUp
Party member
Posts: 105
Joined: Fri Apr 21, 2017 9:17 am

destroy a physics object when it collides with other ?

Post by PGUp »

so let say I have 10 physics rectangle and 1 other physics platform, and I want to destroy the rectangle everytime the rectangle collides with it.. I use: table.remove(table, i) it works fine for non physics object.. but on physics object.. 1 or more object will dissapear.. anyone know how to fix it ?

Code: Select all

function love.load()

love.physics.setMeter(64)
world = love.physics.newWorld(0, 9.8 * 64, true)

Nblock = {}

--adding platform
Nplatform = {}
platform = {}
platform.body = love.physics.newBody(world, 0, 500, "static")
platform.shape = love.physics.newRectangleShape(700, 25, 1400, 50)
platform.fixture = love.physics.newFixture(platform.body, platform.shape, 1)
platform.fixture:setRestitution(0.5)
table.insert(Nplatform, platform)

--using begin contact function to handle collisions in world
world:setCallbacks(beginContact, endContact, preSolve, postSolve)

timeA = 0

end

function love.update(dt)
--updating world
world:update(dt)


--timer for spawning
if timeA < 50 then
timeA = timeA + 1
end


--spawning a physics block every 1 second
if love.keyboard.isDown("space") and timeA == 50 then
block = {}
block.body = love.physics.newBody(world, love.mouse.getX(), love.mouse.getY(), "dynamic")
block.shape = love.physics.newRectangleShape(25, 25, 50, 50)
block.fixture = love.physics.newFixture(block.body, block.shape, 1)
block.fixture:setRestitution(0.5)
table.insert(Nblock, block)
timeA = 0
end

end

function love.draw()
--drawing physics blocks
for i,v in pairs(Nblock) do
love.graphics.rectangle("fill", v.body:getX(), v.body:getY(), 50, 50)
end
--drawing plaform
for i,v in pairs(Nplatform) do
love.graphics.rectangle("fill", v.body:getX(), v.body:getY(), 1400, 50)
end
end


--destroy when the blocks collide with the platform, wont work..
function beginContact(a, b, coll)
for i,v in pairs(Nplatform) do
table.remove(Nblock, i)
end
end
Last edited by PGUp on Sat Jun 24, 2017 3:31 am, edited 3 times in total.
-
User avatar
erasio
Party member
Posts: 118
Joined: Wed Mar 15, 2017 8:52 am
Location: Germany

Re: destroy a physics object when it collides with other ?

Post by erasio »

Can you please just post your code?

Just like the last time it's very hard indeed to actually help you based on like no information at all.

Where do you remove it? How do you handle the contact / collision? What does your setup look like? Do you use classes? Inheritance? ECS? Purely functional?
PGUp
Party member
Posts: 105
Joined: Fri Apr 21, 2017 9:17 am

Re: destroy a physics object when it collides with other ?

Post by PGUp »

erasio wrote: Fri Jun 23, 2017 6:23 am Can you please just post your code?

Just like the last time it's very hard indeed to actually help you based on like no information at all.

Where do you remove it? How do you handle the contact / collision? What does your setup look like? Do you use classes? Inheritance? ECS? Purely functional?
done
-
User avatar
erasio
Party member
Posts: 118
Joined: Wed Mar 15, 2017 8:52 am
Location: Germany

Re: destroy a physics object when it collides with other ?

Post by erasio »

Ah yes. This does make it much easier to help out!

You are insecurely removing elements regardless of the collision from your list.

On beginContact you simply iterate over your platform (which should have one entry) and remove a block from your block list at the same index as your platform (aka the first (/oldest) one).

You are not using the data you get from beginContact at all meaning you completely ignore what is colliding.

There's two ways to fix this quickly.

1. Iterate over Nplatform and check if a or b is equal to platform.fixture. If so then iterate over Nblock and check which block.fixture is equal to a or b (the non platform one).

Code: Select all

function beginContact(a, b, coll)
    for i, platform in ipairs(Nplatform) do
        if platform.fixture == a or platform.fixture == b then
            for j, block in ipairs(Nblock) do
                if block.fixture == a or block.fixture == b then
                    table.remove(Nblock, j)
                    break
                end
            end
        end
    end
end
2. You stop inserting elements to those tables with table.insert and move to an id system instead which allows you to directly address elements within the tables.

Code: Select all

Nblock = {}
NblockId = 1

function love.update(dt)
    [...]
    if love.keyboard.isDown("space") and timeA == 50 then
    [...]
    block.fixture:setRestitution(0.5)
    block.fixture:setUserData({"block", NblockId})
    Nblock[Nblock.id] = block
    NblockId = NblockId + 1
    timeA = 0
end

function beginContact(a, b, coll)
    local aData = a:getUserData()
    local bData = b:getUserData()    
    if aData[1] == "platform" and bData[1] == "block" or aData[1] == "block" and bData[1] == "platform" then
    	if aData[1] == "block" then
    	    Nblock[aData[2]] = nil
    	elseif bData[1] == "block" then
    	    Nblock[bData[2]] = nil
    	end
    end
end
3. You move to an Entity Component System (ECS) where you do not handle the behavior inside of the beginContact function but forward this call to the object owning the fixture which might destroy itself depending on what's implemented there. (This is too complex to give you a short mockup).

Disclaimer. All code is written from mind and not tested. There might be some minor issues with it and it likely isn't the best way to implement this behavior. It's merely intended to give you an idea of how one could do it.
Post Reply

Who is online

Users browsing this forum: Bing [Bot] and 51 guests