lua - ведение таблицы (система частиц) - PullRequest
2 голосов
/ 01 июня 2011

Приведенная ниже функция update() вызывается в каждом кадре игры.Если частица Drop имеет значение y больше 160, я хочу удалить ее из таблицы.Проблема в том, что я получаю сообщение об ошибке «попытка сравнить число с нулем» в строке, указанной ниже:

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 в первую очередь, поскольку я установил его равным nil, когда значение y становится больше 160.

Ответы [ 4 ]

3 голосов
/ 01 июня 2011

Спасибо за ответы, все они были полезны.Вот что в итоге сработало для меня.Вызов 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
2 голосов
/ 01 июня 2011

Вы ищете не в том месте, проблема не в том, что val это nil, это 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]: ?

Кроме того, когда вы устанавливаете val на nil, это может ничего не делать (я считаю, 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
0 голосов
/ 01 июня 2011

Решение JeffK должно работать, но я думаю, что причина его работы не в том, что он перебирает список в обратном направлении, а в том, что он устанавливает particles[i] = nil вместо val = nil. Если вы запускаете val = nil, вы устанавливаете только локальную копию val на nil, а не запись в таблице.

Попробуйте это:

for i,val in ipairs(particles) do
    if(val.y > 160) then
        particles[i]:removeSelf()
        particles[i] = nil;
    end
end
0 голосов
/ 01 июня 2011

Не думаю, что вам разрешено изменять содержимое таблицы, пока ipairs выполняет итерацию по ней.Я смутно помню, что читал мою печатную копию Lua 5.1 Справочное руководство , но сейчас я не могу ее найти.Когда вы устанавливаете val на ноль , он удаляет элемент из частиц таблица.

Вы можете попробовать обработать таблицу в обратном порядке, поскольку ваша функция выполняет полную развертку таблицы частиц , условно удаляя некоторые элементы:

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