2011-05-31 89 views
2

update()函数在游戏的每一帧都被调用。如果Drop粒子的y值大于160,我想将其从表格中删除。问题是,我得到“试图用零来比较数字”的错误,对线下谱写:lua - 表维护(粒子系统相关)

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 from the screen 
      val = nil; 
     end 
    end 
end 

我在做什么错?很显然val是零,但我不明白为什么表迭代会首先找到val,因为当它的y值大于160时,我将它设置为零。

回答

3

感谢您的回答,他们都有帮助。这是最终为我工作的。调用table.remove以保持循环正常运行。

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 
0

我不认为你被允许修改表格的内容,而ipairs正在迭代它。我隐约记得读到我的Lua 5.1 Reference Manual的硬拷贝,但我现在似乎无法找到它。当您设置VAL,它会从颗粒表的元素。

你可以尝试处理反向表,因为你的函数是做颗粒的全扫表,有条件地删除一些项目:

for x = #particles, 1, -1 do 
    if particles[x].y > 160 then 
     particles[x]:removeSelf() 
     particles[x] = nil 
    end 
end 
+1

根据文件说明只适用于下一个和配对。使用ipairs以数字顺序遍历表应该没问题。然而,他只是勉强val,而不是表中的条目http://www.lua.org/manual/5.1/manual.html#pdf-next – Alex 2011-06-01 00:01:19

+0

我试过这段代码(在给条件加上-1并改变之后粒子[x] .val到粒子[x] .y),但我删除一个粒子后得到它:尝试索引字段'?'(一个零值) – clua7 2011-06-01 01:02:18

+0

代码根据clua7的评论更新。无参考错误令人费解。 ['removeSelf()'](http://developer.anscamobile.com/reference/index/objectremoveself)调用将该对象与Corona的显示设备分离,并将其设置为'nil'将其从'particles'表中移除,准备好垃圾收集。然后,'x'应该递减,移动到表中的下一个对象。当您尝试索引字段时会报告什么行? (一个零值)?“ – JeffK 2011-06-01 12:52:40

0

JeffK的解决方案应该工作,但我认为它将工作的原因并不是因为他向后遍历列表,而是因为他正在设置particles[i] = nil而不是val = nil。如果您运行val = nil,则只会将val的本地副本设置为零,而不是表中的条目。

试试这个:

for i,val in ipairs(particles) do 
    if(val.y > 160) then 
     particles[i]:removeSelf() 
     particles[i] = nil; 
    end 
end 
+0

我试过你的代码。我现在不知道这个错误,但奇怪的是它只会删除一个对象。之后它再也不会进入for循环。这就像粒子表被设置为零。 – clua7 2011-06-01 00:44:28

+0

可能发生了什么,那么列表中的第一个元素将被删除,那么因为第一个元素为零,所以循环不会再次运行(当迭代到达无索引时停止)。你可能可以通过在循环结尾压缩数组来解决这个问题,以便它没有间隙,尽管这可能会很棘手。 – Alex 2011-06-01 01:07:03

+0

是的,当达到'nil'值时,for循环将停止。我用'table.remove'更新了我的答案,正确执行删除。 – BMitch 2011-06-01 02:39:43

2

你找错了地方,问题不在于valnil,这是val.y这是nil。看到这个例子:

> 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]: ? 

此外,当您设置valnil,可能不会做任何事情(我相信val是复印件):

> 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 

编辑:删除从一个元素表,你想要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