Page 1 of 2
Why is table.remove making my program crash?
Posted: Thu Oct 27, 2011 6:35 pm
by enderspike
Newb here,
So I have collision checks for entities down, but I'm having trouble removing entities from tables when I want. I remove enemies or bullets from thier respective tables, and everything explodes. Why? What's going wrong? How can I fix it?
Thanks!
Re: Why is table.remove making my program crash?
Posted: Thu Oct 27, 2011 6:58 pm
by ivan
Code: Select all
for first = 1, #PlayerBullets do
for second=1, #Enemies do
if CollisionCheck(PlayerBullets[first], Enemies[second]) then
table.remove(PlayerBullets, first)
table.remove(Enemies, second)
end
end
end
When you remove an element from a table at index "i", it shifts the indices of all following elements.
Try replacing the 2 for loops with something like:
Code: Select all
local i = 1
while i < #playerBullets do
if CollisionCheck ( ) == true then
table.remove ( playerBullets, i )
else
i = i + 1
end
end
Or use pairs to iterate "playerBullets" and instead of calling "table.remove" do
playerBullets
= nil
Notice that in the second case, you can't use "#playerBullets" to check the table size.
Re: Why is table.remove making my program crash?
Posted: Thu Oct 27, 2011 7:14 pm
by bartbes
Other common tricks include marking the values or storing their indexes so you can remove them in a second loop, which may or may not do a reverse traversal.
Re: Why is table.remove making my program crash?
Posted: Thu Oct 27, 2011 7:48 pm
by Robin
bartbes wrote:which may or may not do a reverse traversal.
I wouldn't recommend
not reversing. That way, you get the same index shifting again.
Unless you are storing the values. Then it works.
Of course, that also makes it an order of n less efficient, because then you have to look up the index each time.
Re: Why is table.remove making my program crash?
Posted: Thu Oct 27, 2011 9:43 pm
by enderspike
Got it fixed! Thanks guys. Now I just have to figure out why sometimes multiple enemies get deleted when I hit one. Only sometimes.
Re: Why is table.remove making my program crash?
Posted: Thu Oct 27, 2011 11:21 pm
by Taehl
My usual method goes like this:
Code: Select all
for i=#mobs, 1, -1 do
local m = mobs[i]
if m.health < 0 then table.remove(mobs, i) end
end
Since going backwards means you don't have to worry about the shift.
Re: Why is table.remove making my program crash?
Posted: Fri Oct 28, 2011 7:28 am
by miko
Taehl wrote:My usual method goes like this:
Code: Select all
for i=#mobs, 1, -1 do
local m = mobs[i]
if m.health < 0 then table.remove(mobs, i) end
end
Since going backwards means you don't have to worry about the shift.
If you have one table to traverse, this will work. But not in this case, where you traverse both tables, and any item from both of tables can be removed anytime. So you either mark items for later removal, or create a copy of the tables in your iterator function (so the original tables can be modified without affecting the iterator).
Re: Why is table.remove making my program crash?
Posted: Fri Oct 28, 2011 7:20 pm
by Taehl
miko wrote:Taehl wrote:My usual method goes like this:
Code: Select all
for i=#mobs, 1, -1 do
local m = mobs[i]
if m.health < 0 then table.remove(mobs, i) end
end
Since going backwards means you don't have to worry about the shift.
If you have one table to traverse, this will work. But not in this case, where you traverse both tables, and any item from both of tables can be removed anytime. So you either mark items for later removal, or create a copy of the tables in your iterator function (so the original tables can be modified without affecting the iterator).
*Makes a few tweaks*
Code: Select all
for i=math.max(#mobs, #ents), 1, -1 do
local m,e = mobs[i], ents[i]
if m and m.health < 0 then table.remove(mobs, i) end
if e and e.health < 0 then table.remove(ents, i) end
end
Re: Why is table.remove making my program crash?
Posted: Fri Oct 28, 2011 9:10 pm
by miko
Taehl wrote:miko wrote:Taehl wrote:My usual method goes like this:
Code: Select all
for i=#mobs, 1, -1 do
local m = mobs[i]
if m.health < 0 then table.remove(mobs, i) end
end
Since going backwards means you don't have to worry about the shift.
If you have one table to traverse, this will work. But not in this case, where you traverse both tables, and any item from both of tables can be removed anytime. So you either mark items for later removal, or create a copy of the tables in your iterator function (so the original tables can be modified without affecting the iterator).
*Makes a few tweaks*
Code: Select all
for i=math.max(#mobs, #ents), 1, -1 do
local m,e = mobs[i], ents[i]
if m and m.health < 0 then table.remove(mobs, i) end
if e and e.health < 0 then table.remove(ents, i) end
end
That could work in your case, but in the OP code there was checking for collisions between any of elements from both tables. So it was real 2-D problem, which can not (easily) be "linearized", like your case (in which there are no interactions between mobs and ents elements).
Re: Why is table.remove making my program crash?
Posted: Fri Oct 28, 2011 9:26 pm
by Taehl
miko wrote:So it was real 2-D problem, which can not (easily) be "linearized", like your case (in which there are no interactions between mobs and ents elements).
Argh, fine!
Code: Select all
for i=math.max(#mobs, #ents), 1, -1 do
local m,isDead = mobs[i]
for i=#ents, 1, -1 do
local e = ents[i]
if whateverItIsYoureDoing then
isDead = true
table.remove(ents, i)
end
end
if isDead then table.remove(mobs, i) end
end
The same basic method I presented still applies.