You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Solar2d Lua开发:气球点击无响应及表格对象移除问题求助

戳气球游戏点击无响应及Table移除问题

我正在跟着Solar2d教程做戳气球游戏,想把气球存在table里,点击让气球消失,但加了事件监听器后点击没反应。有两个问题:

  1. 怎么实现点击移除气球图像?
  2. 该在哪里加代码从table里移除被点击的气球?需要在gameLoop里用for循环吗?

之前尝试把事件监听器放在气球创建函数外,出现了“nil value”错误,附上代码:

-----------------------------------------------------------------------------------------
--
-- main.lua
--
-----------------------------------------------------------------------------------------

--prep the physics
local physics = require("physics")
physics.start()
physics.setGravity(0, -20)

--seed the random number generator
math.randomseed( os.time() )

--prep the graphic groups
local backGroup = display.newGroup()
local mainGroup = display.newGroup()
local uiGroup = display.newGroup()

--prep variables
local newBalloon
local tappedBalloon
local balloonTable = {}

--load background
local background = display.newImageRect(backGroup,  "pictures/mainGroup/background.png", 360, 570)
background.x = display.contentCenterX
background.y = display.contentCenterY

--load boundaries
local border = display.newImageRect(mainGroup, "pictures/mainGroup/border.png", 281, 35)
border.x = display.contentCenterX
border.y = display.contentHeight-440
physics.addBody( border, "static" )

local function popBalloon( event )
    local tappedBalloon = event.target
    if event.phase == "began" then
        display.remove(tappedBalloon)
        --removing balloon from table?
    end
end


--creating and storing balloons
local function createBalloon ()
    local newBalloon = display.newImageRect(mainGroup, "pictures/mainGroup/balloon2.png", 118, 118)
    if newBalloon then
        table.insert(balloonTable, newBalloon)
        physics.addBody( newBalloon, "dynamic", { radius=50, bounce=0.2 } )
        --newBalloon.isBullet = true
        newBalloon.alpha = 0.8
        newBalloon.myName = "balloon"
        newBalloon:addEventListener("tap", popBalloon)
    end
    
    local placement = math.random(3)

    if (placement == 1) then
        newBalloon.x = math.random( display.contentWidth )
        newBalloon.y = math.random( 250,500 )
    elseif ( placement == 2 ) then
        newBalloon.x = math.random( display.contentWidth )
        newBalloon.y = math.random( 250,500 )
    elseif ( placement == 3 ) then
        newBalloon.x = math.random( display.contentWidth )
        newBalloon.y = math.random( 250,500 )
    end
end

local function gameLoop()
    createBalloon()
end

gameLoopTimer = timer.performWithDelay( 500, gameLoop)

问题1:实现点击移除气球图像

你的核心错误是给tap事件加了event.phase == "began"判断——tap事件没有phase属性,只有touch事件才会返回阶段信息。直接去掉这个判断,或者把事件换成touch并保留阶段判断即可。

另外,调用display.remove()后,建议把对象设为nil,避免内存泄漏。

问题2:从Table中移除被点击的气球

不需要在gameLoop里做循环,直接在点击事件处理函数里遍历table找到对应气球移除就行。因为每个气球对象是唯一的,用ipairs或倒序遍历table,找到和event.target匹配的元素后用table.remove()删除即可。


修改后的完整代码

-----------------------------------------------------------------------------------------
--
-- main.lua
--
-----------------------------------------------------------------------------------------

--prep the physics
local physics = require("physics")
physics.start()
physics.setGravity(0, -20)

--seed the random number generator
math.randomseed( os.time() )

--prep the graphic groups
local backGroup = display.newGroup()
local mainGroup = display.newGroup()
local uiGroup = display.newGroup()

--prep variables
local balloonTable = {}

--load background
local background = display.newImageRect(backGroup,  "pictures/mainGroup/background.png", 360, 570)
background.x = display.contentCenterX
background.y = display.contentCenterY

--load boundaries
local border = display.newImageRect(mainGroup, "pictures/mainGroup/border.png", 281, 35)
border.x = display.contentCenterX
border.y = display.contentHeight-440
physics.addBody( border, "static" )

local function popBalloon( event )
    local tappedBalloon = event.target
    -- 移除显示对象
    display.remove(tappedBalloon)
    
    -- 倒序遍历table,避免删除元素后索引混乱
    for i = #balloonTable, 1, -1 do
        if balloonTable[i] == tappedBalloon then
            table.remove(balloonTable, i)
            break
        end
    end
    tappedBalloon = nil
end


--creating and storing balloons
local function createBalloon ()
    local newBalloon = display.newImageRect(mainGroup, "pictures/mainGroup/balloon2.png", 118, 118)
    if newBalloon then
        table.insert(balloonTable, newBalloon)
        physics.addBody( newBalloon, "dynamic", { radius=50, bounce=0.2 } )
        newBalloon.alpha = 0.8
        newBalloon.myName = "balloon"
        -- 使用tap事件,无需phase判断
        newBalloon:addEventListener("tap", popBalloon)
    end
    
    -- 三个分支逻辑完全重复,直接简化
    newBalloon.x = math.random( display.contentWidth )
    newBalloon.y = math.random( 250,500 )
end

local function gameLoop()
    createBalloon()
end

gameLoopTimer = timer.performWithDelay( 500, gameLoop)

额外优化点

  • 移除了冗余的全局变量newBalloon和tappedBalloon,改用函数内局部变量,避免全局污染。
  • 简化了气球随机位置的代码,三个分支逻辑完全一致,无需多做判断。

内容的提问来源于stack exchange,提问作者laatto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 03:17:38