function love.mousepressed(x, y, button)
if player.getState(1) == "is-playing" then
if button == "l" then
unit_value = unit_value + 1
table.insert(units,{unit_id = lp.newBody(map, x, y, "kinematic"), img = lg.newImage("gfx/turret3.png"), x = tonumber(x), y = tonumber(y), id = unit_value})
elseif button == "r" then
for _, d in pairs(units) do
local unitX = d.unit_id:getX() - 10
local unitY = d.unit_id:getY() - 10
local unitX_max = d.unit_id:getX() + 10
local unitY_max = d.unit_id:getY() + 10
if x >= unitX and x <= unitX_max and y >= unitY and y <= unitY_max then
d.unit_id:destroy()
table.remove(units,???)
end
end
end
end
end
When I press the left mouse button then the unit/body is created and a value is inserted in the table. But when I press the right mouse button the unit/body is removed BUT the value in the table remains, so how can I remove the value of the body in the table?
You need to give table.remove() the numeric index for the sub-table you want to remove. You could do this by looping through using ipairs() instead of pairs(), and when you find the unit you want to remove then you'll have the index to give to table.remove(). At which point you should break out of the loop since table.remove() will shift all the elements "down" to fill in that hole. For example:
for index, d in ipairs(units) do
local unitX = d.unit_id:getX() - 10
local unitY = d.unit_id:getY() - 10
local unitX_max = d.unit_id:getX() + 10
local unitY_max = d.unit_id:getY() + 10
if x >= unitX and x <= unitX_max and y >= unitY and y <= unitY_max then
d.unit_id:destroy()
table.remove(units, index)
break
end
end
ejmr wrote:You need to give table.remove() the numeric index for the sub-table you want to remove. You could do this by looping through using ipairs() instead of pairs(), and when you find the unit you want to remove then you'll have the index to give to table.remove(). At which point you should break out of the loop since table.remove() will shift all the elements "down" to fill in that hole. For example:
for index, d in ipairs(units) do
local unitX = d.unit_id:getX() - 10
local unitY = d.unit_id:getY() - 10
local unitX_max = d.unit_id:getX() + 10
local unitY_max = d.unit_id:getY() + 10
if x >= unitX and x <= unitX_max and y >= unitY and y <= unitY_max then
d.unit_id:destroy()
table.remove(units, index)
break
end
end
for name, d in pairs(units) do
local unitX = d.unit_id:getX() - 10
local unitY = d.unit_id:getY() - 10
local unitX_max = d.unit_id:getX() + 10
local unitY_max = d.unit_id:getY() + 10
if x >= unitX and x <= unitX_max and y >= unitY and y <= unitY_max then
d.unit_id:destroy()
if d.id == d.id then
table.remove(units,name)
end
end
end
for i=#i,1,-1 do
if units[i].destroy then
table.remove(units, i)
end
end
This works much better because you don't end up looping over the table twice for every deletion (and it's even more efficient in case you have to remove multiple units at once). Also because we iterate backwards there is no issue with table.remove shifting the elements around.
You need to take care when interacting with your elements though, you should consider units that have .destroy set as nonexistant. (if you don't care about a one-frame delay there you can of course dont mind, but watch out that you don't kill thing twice etc.)
S0lll0s wrote:You need to take care when interacting with your elements though, you should consider units that have .destroy set as nonexistant. (if you don't care about a one-frame delay there you can of course dont mind, but watch out that you don't kill thing twice etc.)
This. It took me a few minutes to understand why, in a game I was making (I'm out of ideas for now), killing an enemy with a gun, uzi or rifle yelded the correct amount of XP but killing it with a shotgun gave me a fuckload more. (I was killing it once for every bullet that hit it.)
lf = love.filesystem
ls = love.sound
la = love.audio
lp = love.physics
lt = love.thread
li = love.image
lg = love.graphics
units[unit] = true -- or whatever value, it doesn't really matter
Although polling destroyed units like S0lll0s suggested might be useful in some specific circumstances as well. For instance if you want to know precisely how much "overkill damage" you have done or if you want to know when two players hit something in exact same time. Although I wonder how many "one frame ties" like this would you encounter...