【问题标题】:physics doesn't work in lua物理学在lua中不起作用
【发布时间】:2014-03-19 03:43:20
【问题描述】:

这段代码创建了一个大炮和 3 个气球,大炮应该射出一颗可以摧毁气球的子弹,以及单词。在此过程中,大炮应该旋转,当我从屏幕上松开手指时,它会射击。由于某种原因它没有响应,大炮没有旋转,也没有任何子弹射出。

local score = 0
local scoreText
local scoreForLevelComplete
local background
local infoBar
local restartBtn
local cannon
local levelNum
local cannonCharge = {}
local shot = {}
local cannonBall
local impulse = 0
local balloons = {}
local cannonCharge = {}
local shot = {}


function scene:createScene(event)
    local group = self.view

    background = display.newImage( "bkg_clouds.png")
    group:insert(background)
    background.x = 230
    background.y = 195

    scoreText = display.newText( "0", 0, 0, native.systemFont, 32 )
    scoreText:setFillColor( 0,0, 0 )
    scoreText.x = 87
    scoreText.y = 28
    group:insert( scoreText ) 

    questionText = display.newText('a', display.contentCenterX, display.contentWidth/4, native.systemFont, 40)
    group:insert(questionText)

    infoBar = display.newImage ("infoBar.png")
    group:insert(infoBar)
    infoBar.x = 10
    infoBar.y = 25

    restartBtn = display.newImage ("restartBtn.png")
    group:insert(restartBtn)
    restartBtn.x = 470
    restartBtn.y = 300

    cannon = display.newImage ("cannon.png")
    group:insert(cannon)
    cannon.x = 10
    cannon.y = 270

    cannon.anchorX = 0.5
    cannon.anchorY = 0.5
    restartBtn.isVisible = true

    local balloon = display.newImage ('balloon_fat_red.png', 495, 125)
    group:insert(balloon)
    balloon = display.newImage ('balloon_fat_red.png', 495, 175)
    group:insert(balloon)
    balloon = display.newImage ('balloon_fat_red.png', 495, 225)
    group:insert(balloon)

    local balloonText1 = display.newText('\227\129\130', 495, 125)
    balloonText1:setFillColor( 1,1, 0 )
    local balloonText2 = display.newText('\227\129\132', 495, 170)
    balloonText2:setFillColor( 1,1, 0 )
    local balloonText3 = display.newText('\227\129\134', 495, 225)
    balloonText3:setFillColor( 1,1, 0 )

    balloon.name = 'balloon'
    physics.addBody(balloon)
    balloon.bodyType = 'static'
    table.insert(balloons, balloon)      

    group:insert(balloonText1)
    group:insert(balloonText2)
    group:insert(balloonText3)


    function ballCollision(e)
       if (e.other.name == 'balloon') then
            scene.updateScore()
            e.target:removeSelf() 
            print ('remove balloon text')
            e.other:removeSelf()
            audio.play(pop)
        end
    end

    function cannonCharge:touch(e)
        if(e.phase == 'began') then
            impulse = 0
            cannon.isVisible = true
            Runtime:addEventListener('enterFrame', charge)
        end
    end

    function charge()
        local degreesPerFrame = 0.5
        cannon.rotation = cannon.rotation - degreesPerFrame 
        impulse=impulse-0.2

        if(cannon.rotation < -46) then
            cannon.rotation = -46
            impulse = -3.2
        end
    end

    function shot:touch(e)
        if(e.phase == 'ended') then
            Runtime:removeEventListener('enterFrame', charge)
            cannon.isVisible = true
            cannon.rotation = 0

            cannonBall = display.newImage('cannon ball.png', 84, 220)
            physics.addBody(cannonBall, {density = 1, friction = 0, bounce = 0})
            group:insert(cannonBall)

            -- Shoot cannon ball
            cannonBall:applyLinearImpulse(3, impulse, cannonBall.x, cannonBall.y )

            --Collision listener
            cannonBall:addEventListener ('collision', ballCollision)
        end
    end
end

这是我的进入场景功能

function scene:enterScene( event )
    local group = self.view
    background:addEventListener('touch', cannonCharge)
    background:addEventListener('touch', shot) 
end

【问题讨论】:

  • 对不起格式,我编辑了它并添加了一些事件监听器,但气球在球击中后仍然不会消失。
  • 函数 cannonCharge:touch(e) 和函数 shot:touch(e) 持有对象,如果这就是你的意思。此外,只有第三个气球会消失,前两个不会。

标签: lua coronasdk


【解决方案1】:

我知道 Corona 文档说在调用 addEventListener('event', listener) 时侦听器可以是一个表对象,但我从未见过或使用过它。在已发布的代码中,在 createScene 中定义函数没有任何优势,因为它们是全局的,并且您已经拥有一堆或模块局部变量。尝试将侦听器拉出并使其成为常规函数:

local canon
...
local cannonCharge = function(event)
    if event.phase == 'began' then
        impulse = 0
        cannon.isVisible = true
        Runtime:addEventListener('enterFrame', charge)
    end
end

local shot = function(event)
    ...
end

local function charge()
    ...
end

... other local functions ...

function scene:createScene(event)
    ...
end

另外,通过在每个触摸监听器中打印一些内容来确认是否正在调用您的触摸监听器。

最后,也是最重要的一点,您只将最后一个气球添加到物理中,因此子弹只能与那个气球相撞。与您必须在每个气球创建后添加group:insert(balloon) 相同的方式,您应该在每个组插入后添加physics.addBody(balloon, ...)。这样做:

local balloon1 = display.newImage ('balloon_fat_red.png', 495, 125)
local balloon2 = display.newImage ('balloon_fat_red.png', 495, 175)
local balloon3 = display.newImage ('balloon_fat_red.png', 495, 225)

group:insert(balloon1)
group:insert(balloon2)
group:insert(balloon3)

physics.addBody(balloon1)
physics.addBody(balloon2)
physics.addBody(balloon3)

balloon1.bodyType = 'static'
balloon2.bodyType = 'static'
balloon3.bodyType = 'static'

table.insert(balloons, balloon1)      
table.insert(balloons, balloon2)      
table.insert(balloons, balloon3)      

那里有很多代码重复,添加更多的气球需要更改很多行,所以你不妨将重复的代码分解成一个函数:

local function createBalloon(x, y)
    local balloon = display.newImage ('balloon_fat_red.png', x, y)
    group:insert(balloon)
    physics.addBody(balloon)
    balloon.bodyType = 'static'
    table.insert(balloons, balloon)      
end

createBalloon(495, 125)
createBalloon(495, 175)
createBalloon(495, 225)

它的好处是,如果您需要更多气球,您不会忘记任何设置,并且任何新设置都放在 createBallon 中,因此所有气球都具有相同的配置(x、y 等函数参数除外)。

更新:确定碰撞处理程序中的哪个气球

取决于您为什么需要知道哪个气球。例如,如果是因为气球 1 给出 10 分,而 3 给出 30 分,那么有更好的方法:您可以将字段添加到对象中,就像您可以有 balloon1.points = 10、balloon2.points = 30 等(你可以这样做createBalloon) 的函数参数,在碰撞处理程序中只需使用 score = score + e.other.points。您应该只需要使用Local Collision Handling,因为只需要知道炮弹何时与气球碰撞即可。要确定 e.other 是否是气球,最简单的方法是在创建气球时添加一个属性:

local function createBalloon(x, y, balloonText)
    local balloon = ...
    ...
    balloon.isBalloon = true -- only balloon objects will have this
    balloon.label = balloonText
end

关于上面的几个注意事项:另一个自定义属性是label,因为您想在碰撞处理程序中删除气球文本,最简单的方法是为其设置一个属性。但是不要在碰撞处理程序中移除涉及碰撞的对象,如that document 中所述,使用延迟移除。所以你的处理程序变成了

function ballCollision(e)
   if e.other.isBalloon then
        scene.updateScore(e.other.points)

        timer.performWithDelay(1, e.target.removeSelf, e.target) 
        timer.performWithDelay(1, e.other.removeSelf,  e.target) 

        e.other.label:removeSelf() -- this is ok: not involved in collision
        audio.play(pop)
    end
end

【讨论】:

  • 如果我使用 add local at finction charge() 它会给我一个错误,“断言错误”但如果我不使用本地,球只会使第三个气球消失而不是第一个或第二个。
  • @user3305142 已更新。
  • 如果我想比较我的子弹击中哪个气球,我使用气球 1、2、3 会更好吗?例如,在 ballCollision(e) 中,我将测量球是否击中了第二个气球,所以 if (event.object1.name == 'balloon1') then...else if (event.object2.name == '气球2')然后...
  • 我正试图参加一个问答游戏,但我用大炮击中了正确的答案。那我应该使用 event.other.name 吗?似乎 object1、object2 和 object3 更有意义。
  • @user3305142 请参阅更新以了解此说明。
【解决方案2】:

您已将气球声明为数组并使用气球 作为变量,同时将图像分配给它们。所以你需要声明 3 个单独的气球对象,比如气球文本,或者如果你使用数组,那么你需要像这样声明。

for i=1,3 do
  balloon[i] = display.newImage ('balloon_fat_red.png', 495, 225)
  group:insert(balloon[i])
end

所以它会识别你要射哪个气球。

【讨论】:

  • 如果是这样,我如何将所有 3 个气球插入气球表,因为它们都有不同的对象名称?
  • 而且代码也意味着3个气球会在同一个位置产生3次。
  • 不需要在气球表中插入气球,因为它已经是表了。您可以根据自己的选择更改气球位置。即使用数组进行位置或进行数学计算。
  • 我现在明白了,所以我假设我不需要插入表格的行,只有这些代码:balloon.name = 'balloon[i]'physics.addBody(balloon[i]) balloon.bodyType = '静态'
  • balloon.name = 'balloon[i] 有一些问题,它给了我一个错误“尝试索引字段”(一个零值)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-16
  • 2014-01-02
相关资源
最近更新 更多