Removing bodies Box2D
Posted: Tue Oct 22, 2013 1:17 pm
Dear People,
struggling for a while now I'm hoping someone can help me out with Box2D physics.
The problem is it is trying to use a body that is destroyed. Regarding safe deletion of bodies I'm trying to use a queu and a tick counter.
The idea behind it is that it updates the world. The enitity''asteroid'' (circle) triggers bodyQueu.add(bullet[bulletID].body) correctly on collision via Callback.
So in the collision callback beginContact it adds the bullet to the bodyQueu, ready for deletion. If you would instantly remove the body via bullet[bulletID]:body:Destroy() it would crash the game as it requires the object for drawing (its still in use). The current tick (per example 72) gets added to the body. Every update the ticker updates by 1, when its 73 it is allowed to delete the body. It first updates the bodyQueu (see if something is there for deletion) then it starts with the world calculations.
Does anyone knows what is going wrong, cause it keeps saying the body is in use when Im trying to delete it! Ive read about the workaround by removing the shape from all contact categories (https://love2d.org/wiki/Remove_Workaround). But this seemed like a cleaner way....
Is the workaround the only possibility or am I missing something?
Thanks in advance
NOTE: I know it is Queue yet Im a lazy typer....
struggling for a while now I'm hoping someone can help me out with Box2D physics.
The problem is it is trying to use a body that is destroyed. Regarding safe deletion of bodies I'm trying to use a queu and a tick counter.
Code: Select all
bodyQueu = {}
function bodyQueu.add(givenBody)
if bodyID == nil then bodyID = 1 end
bodyQueu[bodyID] = {}
bodyQueu[bodyID].body = givenBody
bodyQueu[bodyID].tick = bodyQueu.tick --This adds the current number the ticker is at
bodyID = bodyID + 1
end
Code: Select all
function bodyQueu.update(dt)
--Only do the following if there is anything in the Queu to be deleted
if(#bodyQueu ~= nil) then
--Loop through the list in the Queu
for bodyID = 1, #bodyQueu do
--If the tick the body was added is not equal to the current tick (so its not used by the world atm?)
if(bodyQueu[bodyID].tick ~= bodyQueu.tick) then
--If the body still excists and isnt allready deleted and is not used by the world then remove it and remove it from the Queu table
if(bodyQueu[bodyID] ~= nil and world:isLocked() == false) then
bodyQueu[bodyID].body:destroy()
table.remove(bodyQueu, bodyID)
end
end
end
end
--This makes the ticker never go over 100
if(bodyQueu.tick >= 100) then
bodyQueu.tick = 0
else
bodyQueu.tick = bodyQueu.tick + 1
end
end
Code: Select all
--The ticker starts at 0
function love.load()
bodyQueu.tick = 0
end
So in the collision callback beginContact it adds the bullet to the bodyQueu, ready for deletion. If you would instantly remove the body via bullet[bulletID]:body:Destroy() it would crash the game as it requires the object for drawing (its still in use). The current tick (per example 72) gets added to the body. Every update the ticker updates by 1, when its 73 it is allowed to delete the body. It first updates the bodyQueu (see if something is there for deletion) then it starts with the world calculations.
Code: Select all
function love.update(dt)
--Dont ever ever go faster then 60 calculations per second NOTE: Not frames per second!
local MAX_DT = 1/60;
if(dt > MAX_DT) then
dt = MAX_DT
end
--Updates the physics world
bodyQueu.update(dt)
world:update(dt)
end
Is the workaround the only possibility or am I missing something?
Thanks in advance
NOTE: I know it is Queue yet Im a lazy typer....