每次重启都会增加游戏速度 - 电晕

时间:2014-04-08 06:06:13

标签: lua corona corona-storyboard corona-director

我试图在日冕上制作一个喷气背包兜风概念游戏。首先,与其他sdk不同的是,当您更改场景时,前一个场景会自动删除,在日冕中你必须自己移除每个物体并自行运作。

一周后我终于能够在改变场景时移除物体,但现在我遇到了一个新问题。每当我改变场景并回到游戏屏幕时,激光和导弹的速度每次都会增加(可能两次?)。我怎样才能重置速度? 我甚至添加了另一个" gameStatus"变量来删除事件监听器并尝试打印它,但游戏状态从未实际返回"结束",它总是"运行"。这是gameScene屏幕,一切都在发生


编辑:我刚刚注意到了一些事情,例如,如果已经生成了3个对象,那么在重新加载屏幕后,前3个对象似乎很快,而正常情况从第4个开始。

local composer = require( "composer" )
local scene = composer.newScene()
local physics = require( "physics" )
physics.start()

local image, text1

local function onSceneTouch( self, event )
    if event.phase == "began" then      
        composer.gotoScene( "startScreen", "fade", 400  )       
        return true
    end
end

function scene:create( event )
    local sceneGroup = self.view

    -- Variable
    ---------------------------------------
    sW = display.contentWidth
    sH = display.contentHeight

    -- trying to reset gameStatus on restart
    gameStatus = "ended"
    gameStatus = "running"


    --------------------------------------------------------
    backgroundTiles = {}

    drawBackground = function()
        cieling = display.newRect( 0, 0, 2 * sW, sH * 0.05)
        physics.addBody( cieling, "static", { density=0, friction=0, bounce=0 } )
        cieling.x, cieling.y = cieling.contentWidth / 4, cieling.contentHeight * 0.25
        cieling.alpha = 0
        cieling.name = "ceiling"

        ground = display.newRect( 0, sH, 2 * sW, sH * 0.05)
        physics.addBody( ground, "static", { density=3, friction=1, bounce=0.1 } )
        ground.x, ground.y = ground.contentWidth / 4, sH - ground.contentHeight * 0.25
        ground.alpha = 0
        ground.name = "ground"

    end

    drawBackground()
    --------------------------------------------------------


    --------------------------------------------------------
    drawBird = function()
        bird = display.newImageRect( "a/img/hero/hero.png", 80, 58)
        bird.x, bird.y = 0 - sW * 0.1, ground.y - ground.contentHeight - 10
        bird.isFixedRotation = true; bird.angularVelocity = 0;
        physics.addBody( bird, { density=1, friction=0.5, bounce=0.1 } )
        bird.name = "bird"
        sceneGroup:insert( bird )

        bird:addEventListener( "collision", onCollision )
    end

    coinsCollected, tokensCollected = 0, 0

    birdFlight = function()
        if ( gameStatus == "running" ) then
            transition.to(bird, {
                y = bird.y - 75,
                transition = easing.outQuad,
                onComplete = function() end
            })
            function birdFlight()
                --transition.to( bird, { rotation=-45, time=300 } )
            end
            birdFlight()
            function birdFall()
                --transition.to( bird, { rotation=90, time=300 } )
            end
            timer.performWithDelay(700, birdFall, 1)
        end
    end
    display.currentStage:addEventListener( "tap", birdFlight )

    function onCollision(event)
        if event.phase == "began" then
            if event.other.name == "coin" then
                coinsCollected = coinsCollected + 1
            end
            if event.other.name == "token" then
                tokensCollected = tokensCollected + 1
            end
            if event.other.name == "missile" or event.other.name == "laser" or event.other.name == "rod" then
               -- game ended
            end
        end
    end

    drawBird()

    function atFrame(event)
        if gameStatus == "running" then
            bird.x,bird.y = sW / 3,bird.y + 9
            if ( bird.y > sH - 70) then bird.y = sH - 70 end
            if ( gameStatus == "ended" ) then bird.y = bird.y + 15 end
        end
    end
    Runtime:addEventListener( "enterFrame", atFrame )

    --------------------------------------------------------



    --------------------------------------------------------
    missile, missileAlert, missileMoving = {}, {}, {}

    function removeMissile(i)
        local onEnterFrame = function( event )
            if missile[i] ~= nil and missile[i].x ~= nil and gameStatus == "running" then
                if missile[i].x < -100 then
                    display.remove( missile[i] )
                    missile[i] = nil
                end
            end
        end
        Runtime:addEventListener( "enterFrame", onEnterFrame )

        print(gameStatus)

        if gameStatus == "ended" then
            Runtime:removeEventListener( "enterFrame", onEnterFrame )
        end 
    end


    function flyMissile(i)
        local onEnterFrame = function( event )
            if missile[i] ~= nil and missile[i].x ~= nil and missile[i].y ~= nil and gameStatus == "running" then
                if missileMoving[i] == true then
                    missile[i].y = bird.y
                end
                missile[i].x = missile[i].x - 5
                if missileAlert[i] ~= nil then
                    if missileMoving[i] == true then
                        missileAlert[i].y = bird.y
                    end                 
                    if missile[i].x < sW then
                        display.remove( missileAlert[i] )
                        missileAlert[i] = nil
                    end                 
                end
            end
        end
        Runtime:addEventListener( "enterFrame", onEnterFrame )

        print(gameStatus)

        if gameStatus == "ended" then
            Runtime:removeEventListener( "enterFrame", onEnterFrame )
        end 
    end


    function holdMissile(i)
        local onEnterFrame = function( event )
            if missile[i] ~= nil and missile[i].x ~= nil and gameStatus == "running" then
                if missile[i].x < sW * 1.5 then
                    if missileAlert[i] ~= nil then
                        missileAlert[i]:setFillColor(1,1,0)
                    end
                    missileMoving[i] = false
                end
            end
        end
        Runtime:addEventListener( "enterFrame", onEnterFrame )

        print(gameStatus)

        if gameStatus == "ended" then
            Runtime:removeEventListener( "enterFrame", onEnterFrame )
        end 
    end


    function spawnMissile(i)

        missile[i] = display.newRect( sW*2, sH/2, 80, 80 )
        missileAlert[i] = display.newRect( sW-80, bird.y, 80, 80 )
        physics.addBody(missile[i],"kinematic",{isSensor=true})
        missile[i].name = "missile"
        sceneGroup:insert( missile[i] )
        sceneGroup:insert( missileAlert[i] )

        missileMoving[i] = true

        flyMissile(i)
        removeMissile(i)
        holdMissile(i)

    end

    spawnMissile(1)
    --------------------------------------------------------


    --------------------------------------------------------
    laser = {}

    function moveAndRemovelaser(i)
        local onEnterFrame = function( event )
            if laser[i] ~= nil and laser[i].x ~= nil and gameStatus == "running" then               
                laser[i].x = laser[i].x - 5
                if laser[i].x < 0 - sW / 2 then
                    display.remove( laser[i] )
                    laser[i] = nil
                end
            end
        end
        Runtime:addEventListener( "enterFrame", onEnterFrame )

        print(gameStatus)

        if gameStatus == "ended" then
            Runtime:removeEventListener( "enterFrame", onEnterFrame )
        end 
    end

    function spawnlaser(i)

        laserSize = math.random(1,2)
        laserPosition = math.random(1,3)
        laserRotation = math.random(1,4)

        if laserSize == 1 then
            laser[i] = display.newRect( 100,100,50,sH/3 )
        else
            laser[i] = display.newRect( 100,100,50,sH/2 )
        end

        sceneGroup:insert( laser[i] )

        laser[i].x = sW * 2
        laser[i].y = sH / 2
        laser[i].name = "laser"

        if laserPosition == 1 and laserRotation ~= 4 then
            laser[i].y = sH * 0.05 + 12
            laser[i].anchorY = 0
        elseif laserPosition == 3 and laserRotation ~= 4 then
            laser[i].y = sH * 0.95 - 12
            laser[i].anchorY = 1
        end

        if laserPosition == 1 and laserRotation == 4 then
            laser[i].y = sH * 0.05 + laser[i].contentHeight / 2
        elseif  laserPosition == 3 and laserRotation == 4 then
            laser[i].y = sH * 0.95 - laser[i].contentHeight / 2
        end

        if laserRotation == 1 then
            laser[i].rotation = -45
        elseif laserRotation == 2 then
            laser[i].rotation = 0
        elseif laserRotation == 3 then
            laser[i].rotation = 45
        elseif laserRotation == 4 then
            local onEnterFrame = function( event )
                if laser[i] ~= nil and laser[i].rotation ~= nil then
                    laser[i].rotation = laser[i].rotation + 5
                end
            end
            Runtime:addEventListener( "enterFrame", onEnterFrame )
        end

        laser[i]:setFillColor(1,1,0)
        physics.addBody(laser[i],"kinematic",{isSensor=true})

        moveAndRemovelaser(i)
    end

    spawnlaser(1)
    --------------------------------------------------------




    image = display.newRect (100,100,100,100)
    image.x = display.contentCenterX
    image.y = display.contentCenterY

    sceneGroup:insert( image )

    image.touch = onSceneTouch

    text1 = display.newText( "Game Screen", 0, 0, native.systemFontBold, 24 )
    text1:setFillColor( 255 )
    text1.x, text1.y = display.contentWidth * 0.5, 50
    sceneGroup:insert( text1 )
end

function scene:show( event )

    local phase = event.phase

    if "will" == phase then
        gameStatus = "ended"
    end

    if "did" == phase then
        print( "4" )
        composer.removeScene( "startScreen" )
        image:addEventListener( "touch", image )
        gameStatus = "running"
    end

end

function scene:hide( event )
    local phase = event.phase
    if "will" == phase then
        print( "5" )
        gameStatus = "ended"
        image:removeEventListener( "touch", image )
        Runtime:removeEventListener( "enterFrame", onEnterFrame )
    end
end

function scene:destroy( event ) 
    print( "6" )
end


scene:addEventListener( "create", scene )
scene:addEventListener( "show", scene )
scene:addEventListener( "hide", scene )
scene:addEventListener( "destroy", scene )


return scene

2 个答案:

答案 0 :(得分:1)

您遇到此问题是因为您要注册两次事件侦听器。

只有在场景进入和退出时才需要添加和删除它们。删除游戏对象的适当位置是scene:destroy()和scene:hide()

我的建议是,您尝试重新组织代码并尝试遵循以下准则:

  • scene:create():第一次使用场景时会发生这种情况。你想在这里创建你的游戏对象。此事件只会发生一次,除非场景被销毁然后再次使用。

  • scene:show():您想在此处注册所有事件监听器(触摸等)并设置您的游戏。每次显示场景时都会调用此函数。这里注册的每个事件监听器都应该取消注册,以防止双重触发。

  • scene:hide():您想在此取消注册所有事件侦听器。这样可以防止下一个场景触发前一个场景听众的事件。

  • scene:destroy():您想删除此处的所有游戏对象(图片,文本,小部件等)。不再需要场景,应该清理所有东西。

为了更好地了解Scene的工作方式,我建议您阅读此文档: http://coronalabs.com/blog/2014/01/21/introducing-the-composer-api-plus-tutorial/

答案 1 :(得分:0)

所以我最终创建了一个函数并将所有removeEventListener放在该函数中,并在游戏结束时调用该函数。 为了将来参考,请始终保留您在屏幕中任意位置创建的所有计时器和事件监听器的列表,并在结束游戏时将它们全部删除

相关问题