Why is table.remove making my program crash?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
enderspike
Prole
Posts: 10
Joined: Tue Oct 11, 2011 6:37 pm

Why is table.remove making my program crash?

Post 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!
Attachments
Rodger2.love
(723 Bytes) Downloaded 79 times
User avatar
ivan
Party member
Posts: 1915
Joined: Fri Mar 07, 2008 1:39 pm
Contact:

Re: Why is table.remove making my program crash?

Post 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.
User avatar
bartbes
Sex machine
Posts: 4946
Joined: Fri Aug 29, 2008 10:35 am
Location: The Netherlands
Contact:

Re: Why is table.remove making my program crash?

Post 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.
User avatar
Robin
The Omniscient
Posts: 6506
Joined: Fri Feb 20, 2009 4:29 pm
Location: The Netherlands
Contact:

Re: Why is table.remove making my program crash?

Post 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.
Help us help you: attach a .love.
enderspike
Prole
Posts: 10
Joined: Tue Oct 11, 2011 6:37 pm

Re: Why is table.remove making my program crash?

Post 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.
Attachments
Rodger2.love
(787 Bytes) Downloaded 86 times
User avatar
Taehl
Dreaming in associative arrays
Posts: 1025
Joined: Mon Jan 11, 2010 5:07 am
Location: CA, USA
Contact:

Re: Why is table.remove making my program crash?

Post 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.
Earliest Love2D supporter who can't Love anymore. Let me disable pixel shaders if I don't use them, dammit!
Lenovo Thinkpad X60 Tablet, built like a tank. But not fancy enough for Love2D 0.10.0+.
User avatar
miko
Party member
Posts: 410
Joined: Fri Nov 26, 2010 2:25 pm
Location: PL

Re: Why is table.remove making my program crash?

Post 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).
My lovely code lives at GitHub: http://github.com/miko/Love2d-samples
User avatar
Taehl
Dreaming in associative arrays
Posts: 1025
Joined: Mon Jan 11, 2010 5:07 am
Location: CA, USA
Contact:

Re: Why is table.remove making my program crash?

Post 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
Earliest Love2D supporter who can't Love anymore. Let me disable pixel shaders if I don't use them, dammit!
Lenovo Thinkpad X60 Tablet, built like a tank. But not fancy enough for Love2D 0.10.0+.
User avatar
miko
Party member
Posts: 410
Joined: Fri Nov 26, 2010 2:25 pm
Location: PL

Re: Why is table.remove making my program crash?

Post 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).
My lovely code lives at GitHub: http://github.com/miko/Love2d-samples
User avatar
Taehl
Dreaming in associative arrays
Posts: 1025
Joined: Mon Jan 11, 2010 5:07 am
Location: CA, USA
Contact:

Re: Why is table.remove making my program crash?

Post 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.
Earliest Love2D supporter who can't Love anymore. Let me disable pixel shaders if I don't use them, dammit!
Lenovo Thinkpad X60 Tablet, built like a tank. But not fancy enough for Love2D 0.10.0+.
Post Reply

Who is online

Users browsing this forum: Google [Bot] and 6 guests