从内存中有效删除对象

时间:2014-07-02 19:44:47

标签: lua corona

我在main.lua中有以下代码 我想要做的就是生成矩形,将它们添加到物理中以便它们可以从屏幕上掉下来,一旦它们的y大于屏幕高度(意味着它们不再可见)就从内存中删除矩形,并删除那些矩形。被用户触动。

这是我的代码

local physics = require( "physics")
physics.start( )

--table to hold dynamically created rectangles
local rects={}
--used as index for table
local numRect=0

--event handler for rectangle touch
local function rectTouch(event)
    event.target:removeSelf( )
    event.target = nil
end

--function for spawning rectangles
local function spawnRect()
    numRect = numRect + 1
    rects[numRect] = display.newRect( display.contentWidth/2, 200, 200, 200)
    rects[numRect]:setFillColor( 1,1,1 )
    physics.addBody( rects[numRect], "dynamic",{density=1, friction=0,2, bounce=0  })
    rects[numRect]:addEventListener( "touch", rectTouch )
end

--function for removing rectangles which are no more visible
local function removeInactiveRects()
    for i = 1, #rects do
        if rects[i] ~= nil  then
            if rects[i].y > display.contentHeight + 100 then
                rects[i]:removeSelf( )
                rects[i] = nil
            end
        end

    end
end



timer.performWithDelay( 1000, spawnRect, -1 )
timer.performWithDelay( 2000, removeInactiveRects,-1 )

我得到一个错误removeInactiveRects函数,说明尝试将数字与nil进行比较,我想负责这个的语句是rects[i] ~= nil,但我不知道为什么。另外,它是从内存中删除对象的正确方法吗?

3 个答案:

答案 0 :(得分:2)

问题在于触摸rectTouch功能,您不仅需要删除矩形,还需要删除rects[]表中的参考。您可以使用id值创建矩形,这样您就可以在事件函数中识别它们并删除它们。

--event handler for rectangle touch
local function rectTouch(event)
    local i = event.target.id
    event.target:removeSelf( )
    event.target = nil
    rects[i] = nil
end

--function for spawning rectangles
local function spawnRect()
    numRect = numRect + 1
    rects[numRect] = display.newRect( display.contentWidth/2, 200, 200, 200)
    rects[numRect]:setFillColor( 1,1,1 )
    rects[numRect].id = numRect
    physics.addBody( rects[numRect], "dynamic",{density=1, friction=0,2, bounce=0  })
    rects[numRect]:addEventListener( "touch", rectTouch )
end

我也是Corona的新人,所以我不确定,但也许你可以创造一些"地面物体"在底部+ 500并检测碰撞以移除矩形。 看collision detection guide

答案 1 :(得分:2)

问题是语句event.target = nil也没有将相应的rects[i]设置为nil,它只将目标从显示对象转换回常规表。因此,在此声明之后,rects[i]对应于触摸目标的i包含常规表对象,而不是nil,并且此表对象没有y字段。只要您在显示对象上removeSelf,请确保从其他对象(例如rects等表)中删除引用。

此外,关于物体低于某个高度后的移除,有几种方法可以做到这一点:

  1. 一种是制作透明几何体(例如线条),它是具有“isSensor”= true的物理体。在碰撞处理程序中,必须使用timer.performWithDelay(function()event.target:removeFelf()end),因为您无法立即删除属于碰撞事件的对象。
  2. 另一种方法是使用PhysicsContact:isEnabled()并在碰撞处理程序中禁用碰撞并安排删除对象。
  3. 另一种方法是在运行时对象及其处理程序中使用enterFrame,检查任何具有y>的对象。 YMAX。可以立即删除这些对象。
  4. 最后,您每2秒检查一次的技术也适用。
  5. 但#4技术每2秒循环遍历所有“活”框,而基于物理的技术(#1和#2)仅对应删除的那些框使用计算周期。 OTOH,碰撞检测本身有些苛刻,但在2D中可能没那么多。 enterFrame方法(#3)可能有点矫枉过正,因为它在每一帧(30次/秒)被调用,而你只是想删除该对象以使物理学从不再发展的物体中解放出来是可见的,但是如果对象超过阈值,或者一秒钟之后,这种清理是否正确无关紧要。

    这一点在Corona的碰撞文档中都有解释。

答案 2 :(得分:0)

只需使用:

if rects[i] and rects[i].y > display.contentHeight + 100 then

之所以发生这种情况是因为删除了一些rects,因此表中的索引为空。如果它是空的,那么显然它不能有.y参数。

您也可以通过插入对象来避免它:

local localRect = display.newRect( display.contentWidth/2, 200, 200, 200)
rects:insert(localRect)

而不是使用

if rects[i] ~= nil then

使用

if rects[i] then

表示“如果在[i]中有任何对象(不是”nil“而非”false“值)