lua - table maintenance (particle system related)
The update()
function below gets called on every frame of a game. If the Drop
particle has y value greater than 160 I want to remove it from the table. The problem is that I get "attempt to compare number with nil" errors, on the line notated below:
local particles = {};
function update()
local num = math.random(1,10);
if(num < 4) then
local drop = Drop.new()
table.insert ( particles, drop );
end
for i,val in ipairs(particles) do
if(val.y > 160) then --ERROR attempt to compare number with nil
val:removeSelf(); --removeSelf() is Corona function that removes the display object fro开发者_JAVA百科m the screen
val = nil;
end
end
end
What am I doing wrong? Obviously val
is nil, but I don't understand why the table iteration would find val in the first place since I set it to nil when it's y value gets larger than 160.
Thanks for the answers, they were all helpful. Here is what ended up working for me. The table.remove
call is necessary to keep the loop running properly.
for i = #particles, 1, -1 do
if particles[i].y > 160 then
local child = table.remove(particles, i)
if child ~= nil then
display.remove(child)
child = nil
end
end
end
You're looking in the wrong place, the problem isn't that val
is nil
, it's val.y
that's nil
. See this example:
> x=nil
> if x.y > 10 then print("test") end
stdin:1: attempt to index global 'x' (a nil value)
stack traceback:
stdin:1: in main chunk
[C]: ?
> x={y=nil}
> if x.y > 10 then print("test") end
stdin:1: attempt to compare number with nil
stack traceback:
stdin:1: in main chunk
[C]: ?
Also, when you set val
to nil
, that may not be doing anything (I believe val
is a copy):
> t={"a", "b", "c", "d"}
> for i,val in ipairs(t) do print(i, val) end
1 a
2 b
3 c
4 d
> for i,val in ipairs(t) do if i==3 then print("delete", val); val=nil end end
delete c
> for i,val in ipairs(t) do print(i, val) end
1 a
2 b
3 c
4 d
Edit: to delete an element from a table, you want table.remove
:
> t[3]=nil
> for i,val in ipairs(t) do print(i, val) end
1 a
2 b
> t[3]="c"
> for i,val in ipairs(t) do print(i, val) end
1 a
2 b
3 c
4 d
> for i,val in ipairs(t) do if i==3 then print("delete", val); table.remove(t, i) end end
delete c
> for i,val in ipairs(t) do print(i, val) end
1 a
2 b
3 d
JeffK's solution should work, but I think the reason it will work is not because of the fact that he's traversing the list backwards, but because he is setting particles[i] = nil
instead of val = nil
. If you run val = nil
you're only setting the local copy of val to nil, not the entry in the table.
Try this:
for i,val in ipairs(particles) do
if(val.y > 160) then
particles[i]:removeSelf()
particles[i] = nil;
end
end
I don't think you are allowed to modify the contents of a table while ipairs is iterating through it. I vaguely remember reading that my hardcopy of the Lua 5.1 Reference Manual, but I can't seem to locate it now. When you set val to nil, it removes an element from the particles table.
You might try processing the table in reverse, since your function is doing a full sweep of the particles table, conditionally removing some items:
for x = #particles, 1, -1 do
if particles[x].y > 160 then
particles[x]:removeSelf()
particles[x] = nil
end
end
精彩评论