【问题标题】:Corona SDK Lua: Moving items from one table to anotherCorona SDK Lua:将项目从一张桌子移动到另一张桌子
【发布时间】:2016-01-23 05:48:54
【问题描述】:

我是 corona 的新手,正在尝试在移动平台上进行某种对象池化。当他们退出屏幕时,他们会从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 对吧?有点不对劲

【问题讨论】:

  • 我没有完全遵循这里的逻辑,但您几乎可以肯定通过回收它们之间的索引在您的表中创建“洞”。而# 只定义在没有孔的表上。

标签: lua coronasdk lua-table


【解决方案1】:

通过在removeBlock 中说visibleBlocks[block.index] = nil,您正在“阵列”中创建漏洞,这意味着# 所做的不再明确定义。例如,

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-ing 字段。 (table.remove( t, n ) 会将“数组”中n 中的所有元素“向右”移动一位以缩小差距,即

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

table.remove( t, 1 )

结果

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

并且不要在数组内留下间隙。)当您依赖于表/“数组”中事物的顺序而不是它们的绝对位置时,这很有效。

不幸的是,您似乎依赖于所有块的固定位置 (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 所示,并且不会像使用nilpairs 时那样被静默跳过。

如果您依赖表/“数组”中元素的位置(以及隐含的顺序),结果会很好,并且“这实际上是一个块吗?”-检查还不错。


第三种选择——如果您既不依赖顺序也不依赖元素的绝对位置——则不会尝试将表格用作数组。只需将每个块用作键并为其条目分配一个虚拟值(通常为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

当你依赖相对顺序作为绘图顺序或类似的东西时,这个版本会严重崩溃:每当你插入一个元素时,所有条目的顺序可能会完全改变,这会导致块随机弹出到其他块的上方/下方.比较:

t = { [5] = 1, [2] = 1, [8] = 1 }
for k in pairs( t ) do print( k ) end
--> 8, 5, 2
t[3] = 1
for k in pairs( t ) do print( k ) end
--> 8, 5, 2, 3
t[6] = 1
for k in pairs( t ) do print( k ) end
--> 2, 3, 5, 6, 8

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

如果这个潜在问题不适用,这实际上可能会导致总体上最简单的代码(即使您可能需要进行更多重组。)

【讨论】:

    猜你喜欢
    • 2011-10-09
    • 2020-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-10
    • 2015-11-28
    • 2012-05-23
    相关资源
    最近更新 更多