如何使用Corona SDK有效处理对象的移除

刚开始研究很棒的 Corona SDK。

我开始构建一个简单的射击游戏。

我有以下代码:

- 全局变量
local shot = audio.loadSound('shot.mp3')
local bg = display.newImage('bg.png')
local shoot = {}
local Main = {}
local Init = {}

local bullets = display.newGroup()

function update()
    if(bullets.numChildren ~= 0) then
        for i = 1, bullets.numChildren do
            bullets[i].y = bullets[i].y - 8
            - 销毁场景外的子弹
            if(bullets[i].y < (-bullets[i].height-5)) then
                - bullets[i]:removeSelf()
                bullets:remove(bullets[i])
                display.remove(bullets[i])
                return
            end
        end
    end
end
- 初始化函数
function Init ()
    display.setStatusBar(display.HiddenStatusBar)
    local movieclip = require('movieclip')
    local physics = require('physics')
    physics.start()
    physics.setGravity(0, 0)

end

function shoot:tap(e)
        for i = 1, 15 do
    local bullet = display.newImage('bullet.png')
    bullet.x = 150
    bullet.y = 470
    bullet.name = 'bullet'
    physics.addBody(bullet)
    bullets.insert(bullets, bullet)
    end
audio.play(shot)

end

- 主要例程
function Main ()
    Init()
    bg:addEventListener('tap', shoot)
    Runtime:addEventListener('enterFrame', update)
end

Main()

目前它“工作”了;但是当子弹离开屏幕时,整个“游戏”会减慢,并且我可以清楚地看到每个子弹被删除而减慢了游戏。

也许我做错了;也尝试了:removeSelf()函数;结果相同。

原文链接 https://stackoverflow.com/questions/7705439

点赞
stackoverflow用户454950
stackoverflow用户454950

我遇到了同样的问题...并且找到了解决办法:

你正在使用 for 循环删除对象: 如果你在循环中删除对象,比如说你删除了 index 为 1 的对象,那么对象 2 就会移动到对象 1 的位置...所以当循环到对象 2 时,它就不会再检查对象 2(因为它已经移动到对象 1 的位置,而你正在检查对象 3)

for j = 1, buttonGroup.numChildren do
    buttonGroup[1]:removeSelf();        --这将删除所有的子对象
end

for j = 1, buttonGroup.numChildren do
    buttonGroup[j]:removeSelf();        --这将删除交替的子对象
end

希望有用。

2011-12-05 14:08:17
stackoverflow用户1609914
stackoverflow用户1609914

我在我的游戏中长时间地与对象去除进行斗争,而这个游戏使用了很多分级视图。我找到的解决方法是在所有需要删除的对象上使用 = nil, :removeSelf() 以及 .alpha = 0。如果它们都被添加到同一组中,而且该组中没有其他内容,那么也可以使用,但由于组后台设置的各种原因,它并不总是有效。

看起来你已经删除了“子弹”的内容,但那只是一个引用,所以当你说每个子弹都被删除时,实际上它只是从数组中删除了,对象本身仍然存在,需要将其设为 nil 以防止内存泄漏和应用减速(你可能已经发现每个子弹都会减慢应用程序速度,对吗?)

在删除后添加此条件,你就可以解决问题了:

if(not(bullet == nil)) then
    bullet.alpha = 0;
    bullet:removeSelf();
    bullet = nil;
end
2013-12-21 18:04:18
stackoverflow用户3131159
stackoverflow用户3131159

更容易的方法是创建一个表格,像这样

local bulletCache = {}

然后在你的子弹创建代码中添加

table.insert(bulletCache, myBulletObject)

然后在你的退出代码和/或销毁代码中,说

for i = 1, #bulletCache do

--[[
--以下不需要但只是为了让你的代码一致
    pcall(function()
        bullet.alpha = 0
    end)
--]]

    pcall(function()
        bullet:removeSelf()
    end)
    pcall(function()
        bullet = nil
    end)
end
2013-12-26 16:19:40
stackoverflow用户1318711
stackoverflow用户1318711

首先,永远不要试图在GameLoop中执行任何类型的循环。这会降低游戏的帧率,因为它通常需要更多的内存。

现在,似乎您只想在子弹从屏幕上消失时销毁它们,并且您也正在使用物理,那么为什么不利用这一点呢?

以下是您应该遵循的步骤。 (如果您有任何疑问或困难,请向我提问)

1.在屏幕上方略微绘制一个静态物理线。假定y为-20。

    local _yLimit = -20
    local _limitLine = display.newLine(0,_yLimit,display.contentWidth,_yLimit)
    _limitLine.anchorX = 0
    _limitLine.anchorY = 0

2.将所有子弹添加为物理对象。

3.在子弹的底部中心施加力,而不是变换它。[假设子弹具有矩形物理形状,否则决定形状的平衡点]

4.借助“collision”事件侦听器检测碰撞。

5.在碰撞时销毁子弹

这就是简单的方法 :)

如果您仍然存在问题,请告诉我。

2013-12-27 21:16:43