Corona SDK Lua:将项目从一个表格移动到另一个表格

时间:2015-10-23 15:51:30

标签: lua corona lua-table

我是电晕的新手,并试图在移动平台上进行某种对象池化。当他们退出屏幕后,他们会从visibleBlocks移至blocks。当我记录我的两张桌子的数量时,这些数字与他们应该的方式不符......而且我的街区中出现了很长的间隙。

我的块生成:

local color = 'red'
for i = 1, 10 do 
    local block = display.newRect( 0, 0, 60, 2 )
    block.index = i
    block.name = 'block'
    block.isVisible = false
    physics.addBody( block, 'static' )
    blocks[i] = block
    sceneGroup:insert( block )

    block.color = color

    color = switchColor(block)  
end

代码检测块何时离开屏幕

function update()

    for k, block in pairs(visibleBlocks) do
        block.y = block.y - 1
        if block.y < 0 then
            removeBlock(block)
        end
    end

删除阻止代码

function removeBlock(block)

    block.isVisible = false
    block.isBodyActive = false
    blocks[block.index] = block
    visibleBlocks[block.index] = nil


    print (' ')
    print( 'blocks: ' .. #blocks)
    print( 'visible blocks: ' .. #visibleBlocks )

end

在计时器上执行的addblock

function addBlock()
    local block = table.remove( blocks )
    if block ~= nil then
        block.isVisible = true
        block.isBodyActive = true
        visibleBlocks[block.index] = block

        block.x = math.random( 
            block.contentWidth/2 + 20, 
            display.contentWidth - block.contentWidth/2 - 20 
        )
        block.y = display.contentHeight

    end
end

我的控制台输出如下所示:

Oct 23 08:50:16.281: blocks: 0
Oct 23 08:50:16.281: visible blocks: 9
Oct 23 08:50:17.289:  
Oct 23 08:50:17.290: blocks: 0
Oct 23 08:50:17.290: visible blocks: 8
Oct 23 08:50:18.329:  
Oct 23 08:50:18.329: blocks: 10
Oct 23 08:50:18.329: visible blocks: 7
Oct 23 08:50:19.353:  
Oct 23 08:50:19.354: blocks: 9
Oct 23 08:50:19.354: visible blocks: 6
Oct 23 08:50:20.313:  
Oct 23 08:50:20.314: blocks: 8
Oct 23 08:50:20.314: visible blocks: 5
Oct 23 08:50:21.339:  
Oct 23 08:50:21.340: blocks: 0
Oct 23 08:50:21.340: visible blocks: 10
Oct 23 08:50:22.376:  
Oct 23 08:50:22.376: blocks: 7
Oct 23 08:50:22.376: visible blocks: 10
Oct 23 08:50:23.390:  
Oct 23 08:50:23.390: blocks: 6
Oct 23 08:50:23.390: visible blocks: 10
Oct 23 08:50:24.392:  
Oct 23 08:50:24.393: blocks: 5
Oct 23 08:50:24.393: visible blocks: 10
Oct 23 08:50:25.457:  
Oct 23 08:50:25.457: blocks: 4
Oct 23 08:50:25.458: visible blocks: 10

这些数字应该总是加起来10吗?有点不对劲

1 个答案:

答案 0 :(得分:0)

通过在visibleBlocks[block.index] = nil中说removeBlock,您在&#34;数组&#34;中创建漏洞,这意味着#所做的不再明确定义。例如,

function footest( t )  print( ("%d,%s"):format( #t, tostring( t[2] ) ) )  end
footest { 1, nil, 3 }
--> 3,nil
footest { 1, [3] = 3 }
--> 1,nil
t = { 1, 2, 3 } ; t[2] = nil ; footest( t )
--> 3,nil
u = { 1, 2, 3 } ; u[1] = nil ; footest( u )
--> 3,2
u[2] = nil ; footest( u )
--> 3,nil
u[3] = nil ; footest( u )
--> 0,nil

(至少这是当前在我的机器上发生的事情......虽然您可以查看源代码并了解在所有这些情况下您将使用的特定版本会发生什么,参考手册只是说发生的事情是未定义的。)

那么如何解决这个问题?

解决此问题的一种方法是使用table.remove代替nil字段。 (table.remove( t, n )会将&#34; n的所有元素转移到&#34;数组&#34;一个向左移动以缩小差距,即

t = { [1] = 1, [2] = 2, [3] = 3 }

table.remove( t, 1 )

结果

t = { [1] = 2, [2] = 3, [3] = nil }

并且不会在数组中留下空隙。)当你依赖表格中的事物顺序时,这很有效。&#34;数组&#34;但不是他们的绝对位置。

不幸的是,您似乎依赖于所有区块的固定位置(block.index) - 如果是这样,这不会起作用。 (如果 工作,并且我只是误解了您的代码,那么解决这个问题可能是最简单的方法。)

因此,更好的方法是指定false而不是nil。您必须调整update(也许还有其他我没见过的代码),但这些更改很小:

function update()
    for k, block in pairs(visibleBlocks) do
        block.y = block.y - 1
        if block.y < 0 then
            removeBlock(block)
        end
    end
end

变成

function update()
    for k, block in ipairs(visibleBlocks) do
        if block then
            block.y = block.y - 1
            if block.y < 0 then
                removeBlock(block)
            end
        end
    end
end

第一次更改 - 将pairs替换为ipairs - 只要您将表格用作数组, 应该。 (ipairs将停在第一个间隙,这意味着如果你不小心创建了一个洞,很多东西都会丢失,你会得到一个非常明显的错误,比那些小故障更容易调试。 ,如果您的数组包含漏洞,pairs可能无法按升序迭代所有内容 - 请使用t = { 1, 2, 3, [9] = 9, [12] = 12 }进行迭代,使用pairs进行迭代可能会产生1,2,3,12,9的顺序!)

唯一的其他更改是检查if block then …,因为某些块可能不存在,如false所示,并且不会像使用nil和{{1}时一样无声地跳过}。

如果您依赖于表格中的元素的位置(并且,隐含地,顺序),结果将是好的,&#34;数组&#34;并且&#34;这实际上是一个块?&#34 ; - 检查不是太糟糕。

第三种选择 - 如果您既不依赖于订单也不依赖于元素的绝对位置 - 将不会尝试将该表用作数组。只需将每个块用作键,并为其条目指定一个虚拟值(通常为pairs)。 (作为奖励,您不需要记住额外的true - 块索引!)

要添加一个块,只需说出block.index即可删除,只需说出blocks[block] = true即可。迭代所有块,

blocks[block] = nil

但是如果你需要计算块数,你需要一个像

这样的函数
for block in pairs( blocks ) do
    …
end

当你依赖相对顺序作为绘图顺序或类似的东西时,这个版本将会非常可怕:每当你插入一个元素时,所有条目的顺序可能会完全改变,这会导致块在其他地方上下自由弹出。比较:

function size( t )
    local count = 0
    for _ in pairs( t ) do  count = count + 1  end
    return count
end

(如果你运行它,你可以获得一个完全不同的顺序。)

如果这个潜在的问题不适用,这实际上可能会导致整个代码最简单(即使您可能需要重新构建一点。)