Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Scene Not Removing After Going To New Scene
Started by sebfloapps Jul 31 2018 04:58 PM

4 replies to this topic
[TOPIC CONTROLS]
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

sebfloapps

[GLOBAL: userInfoPane.html]
sebfloapps
  • Observer

  • 19 posts
  • Corona SDK

I have this little game working however I am unable to get the current scene removed before I go to a new scene.

 

Game is simple, I have falling objects, and a character, if the character collides with a specific object type then score is increased, but if the character collides with another specific object type then the game is supposed to end and go to the main menu. Which works, but if I go back to the game scene the game is still going, and if I add scene.removeScene() then I get an error.

 

Error: 

Attempt to index field 'view' (a nil value)

Here is the code in question FYI: I have tried typing in the actual scene name into the removeScene() function

local function playerCollision (self, event)
        if event.phase == "began" then
            if event.other.type == "food" then
                score = score + 1
                print(score)
            else
                composer.removeScene(composer.getSceneName( "current" ), true)
                composer.gotoScene("mainMenu", {effect="slideRight", time=300})
            end
            event.other:removeSelf()
        end
    end
    
    --event lister for movement
    bg:addEventListener("touch", movePlayer)
    currentPlayer.collision = playerCollision
    currentPlayer:addEventListener("collision", currentPlayer)
end

Here is the full code 

local composer = require("composer")
local scene = composer.newScene()
local bg
local name 
local score = 0
local pileUp = true
local mRandom = math.random
local mAbs = math.abs
local physics = require("physics")
physics:start()
physics.setDrawMode("hybrid")
local currentPlayer
local ground
local objects = {"apple.png", "mango.png", "orange.png", "pear.png", "bomb.png", "bomb.png", "bomb.png"}
local math = require("math")

function scene:create(e)
bg = display.newImageRect( "images/background2.png", width*2, height )
bg.x = 0
bg.y = y
name = display.newText(e.params.player..":"..score,0,0,system.nativeFont,24)
name.x = 60
name.y = 0
name:setFillColor(.4,0,.2)

currentPlayer = display.newCircle( x, display.actualContentHeight-150, 25 )
physics.addBody(currentPlayer, "static", {density=1, friction = .5, radius = 25})

ground = display.newRect(x,display.actualContentHeight-40,display.actualContentWidth, 50)
scene.view:insert(bg)
scene.view:insert(name)
scene.view:insert(currentPlayer)
scene.view:insert(ground)

end

function scene:show(e)
    local function spawnObjects()
        local objIdx = mRandom(#objects)
        local objName = objects[objIdx]
        local object = display.newImageRect("images/"..objName, 45,45)
        object.x = mRandom(20, display.actualContentWidth-100)
        object.y = mRandom(-10, 0)
        object.rotation = mRandom(-60, -10 )
        if objIdx < 5 then
            object.type = "food"
        else
            object.type = "bomb"
        end
        scene.view:insert(object)
        physics.addBody(object,  "dynamic", {density=1, friction = .5, radius = 25})
    end

    
    timer.performWithDelay(mRandom(1500, 4000),spawnObjects, 0)

    -- Move player 
    local function movePlayer(event)
        if event.phase == "began" then
            local speed = (1500/display.actualContentWidth - display.screenOriginX)*(mAbs(currentPlayer.x - event.x))
            transition.to(currentPlayer, {time=speed, x = event.x})
        end
    end

    local function playerCollision (self, event)
        if event.phase == "began" then
            if event.other.type == "food" then
                score = score + 1
                print(score)
            else
                composer.removeScene(composer.getSceneName( "current" ), true)
                composer.gotoScene("mainMenu", {effect="slideRight", time=300})
            end
            event.other:removeSelf()
        end
    end
    
    --event lister for movement
    bg:addEventListener("touch", movePlayer)
    currentPlayer.collision = playerCollision
    currentPlayer:addEventListener("collision", currentPlayer)
end

function scene:hide(e)
    if e.phase == "will" then
    
    end
end

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

return scene


[TOPIC: post.html]
#2

horacebury

[GLOBAL: userInfoPane.html]
horacebury
  • Corona Geek

  • 2,984 posts
  • Corona SDK

Unrelated...

 

I assume this fails because the physics world is locked during collision events:

event.other:removeSelf()


[TOPIC: post.html]
#3

horacebury

[GLOBAL: userInfoPane.html]
horacebury
  • Corona Geek

  • 2,984 posts
  • Corona SDK

When you say

 

 

the game is still going

do you mean that the display objects etc which you added to the scene are still there?

 

That is what I would expect because you don't have any code removing any of it.

 

I think you are running into the classic problem where developers expect a scene to get recycled automatically.

 

When you add composer.removeScene() where are you putting it? If you put it within the scene being removed you might hit issues.



[TOPIC: post.html]
#4

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 24,714 posts
  • Corona Staff

You cannot remove the scene you are currently in.  There is no reason to. Calling composer.gotoScene() will hide the current scene when it brings the new scene to view. The only reason to remove a scene is to free memory is the scene is taking up too much, but you remove it after it's off-screen in that case. The other quasi-legit reason to remove a scene is if you know you're going back to the scene and you want to do a complete reset of the scene in minimal code.

 

Rob



[TOPIC: post.html]
#5

kakula

[GLOBAL: userInfoPane.html]
kakula
  • Enthusiast

  • 72 posts
  • Corona SDK

i tested your code

 

before removing the scene you need to cancel the timer that spawns objects, which means you need to assign it to a variable like this

xyz=timer.performWithDelay(mRandom(1500, 4000),spawnObjects, 0)

you would also need a Boolean flag to exit the function like this

 

somewhere above:

local exitFlag=false 

spawn function:

 

local function spawnObjects()
        if exitFlag==true then
            return true
        end
        local objIdx = mRandom(#objects)
        local objName = objects[objIdx]
        local object = display.newImageRect("images/"..objName, 45,45)
        object.x = mRandom(20, display.actualContentWidth-100)
        object.y = mRandom(-10, 0)
        object.rotation = mRandom(-60, -10 )
        if objIdx < 5 then
            object.type = "food"
        else
            object.type = "bomb"
        end
        scene.view:insert(object)
        physics.addBody(object,  "dynamic", {density=1, friction = .5, radius = 25})
    end

Player Collision function:

 

local function playerCollision (self, event)
        if event.phase == "began" then
            if event.other.type == "food" then
                score = score + 1
                print(score)
            else
                exitFlag=true
                timer.cancel(xyz)
                composer.removeScene("main2")
                composer.gotoScene("main3")
            end
            event.other:removeSelf()
        end
    end

i have been programming with Corona for 5 years now,i thought i was doing everything correctly, a few months ago i read an article for Rob Miracle on something similar ... i found out that i was not doing anything correctly :-) ... all my apps and games were working fine to the eye ... but internally i was not removing variables or objects, timers... events... properly

 

after reading that article ... my code is much better, and i always clear objects successfully

 

hope this helps

Regards,

Tariq




[topic_controls]
[/topic_controls]