简体   繁体   中英

physics doesn't work in lua

This code creates a cannon and 3 balloons, the cannon should shoot out a bullet that'll destroy balloons, along with the words. DUring the process the cannon should rotate and when i release my finger from the screen it shoots. For some reason it doesn't respond, cannon not rotating nor any bullet is shot.

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

This is my enterscene function

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

I know the Corona docs say that listener can be a table object when call addEventListener('event', listener) but I have never seen or used that. There is no advantage in posted code to have functions defined inside the createScene since they are global and you already have a bunch or module-local variables. Try pulling the listeners out and making them regular functions:

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

Also, confirm that your touch listeners are being called by printing something inside each one.

Finally, and most importantly, you only added the last balloon to the physics so the bullet can only collide with that one balloon. The same way that you had to add group:insert(balloon) after each balloon created, you should have physics.addBody(balloon, ...) after each group insert. So do this:

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)      

There is a lot of code duplication there, and adding more balloons requires many lines to change, so you might as well factor out the duplicate code into a function:

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)

which has the advantage that if you need more balloon you won't forget any settings, and any new settings put in createBallon so all balloons have same config (except for function parameters like x,y etc).

Update: Determine which balloon in collision handler

Depends why you need to know which of the balloons. For example if it's because balloon 1 gives 10 pts while 3 gives 30, then there are better ways: you can add your fields to objects, like you could have balloon1.points = 10, balloon2.points = 30 etc (you would make that a function argument of createBalloon ) and in collision handler just use score = score + e.other.points . You should only need to use Local Collision Handling because only need to know when the cannon ball collides with balloons. To figure out if e.other is a balloon, easiest is to add a property when you create balloon:

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

Couple notes on the above: another custom property is label since you want to remove the balloon text in the collision handler, easiest is to have a property for it. But do not remove objects involved in collision in the collision handler, as explained in that document , use delayed removal. So your handler becomes

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

You have declared balloons as a array and using the balloon as a variable while assigning images to them. So you need to declare 3 separate balloon object like balloon text or if you are using array then you need to declare like this.

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

So it will identify which balloon you want to shoot.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM