Scene problem

Offtopic question:

physics.start() must be at the top or inscene:create or in scene:show?

What I recommend is doing in scene:create();

physics.start()

physics.pause()

This will let you add physics bodies without having them start interacting with themselves.  Since scene:create() is not guaranteed to be called when you go to a scene if it’s cached, you would call physics.start() again in scene:show()'s will phase to resume the simulation.

Rob

In the main chunk is:

function endGamelevel1() ... timer.cancel(timer1) ... end

and when function is called then:

X5EAbRY.png

What is wrong?

What is line 22 of lvl1.lua?

timer.cancel(timer1)

So ask yourself why is timer1 nil?  The likely cause is either it’s out of scope (you defined it in another code block and this block can’t see it).  The other likely cause is it’s really nil.  Have you already cancelled it?  Did you ever create the timer? Are you using timer1 as a different variable.

Rob

I’m stupid. Fixed.

Another problem:

In the main chunk is:

function endGamelevel1() .. button1:removeEventListener("tap", tap) .. end

and in scene:show:

function scene:show( event ) elseif ( phase == "did" ) then ... button1:addEventListener( "tap", tap ) ... end

When function endgamelevel1() is called then:

RX8iiNH.png

creating code of button1 is in scene:create

I can’t troubleshoot your whole app for you.  Perhaps someone in the community would want to help.  Do you have a function named tap?  Why would it be nil or different when you try to remove it.

However, you don’t need to remove tap and touch handlers.  They remove when the object removes.  They can also be added in create.  The listeners that you have to do in scene:show() are Runtime listeners, like enterFrame and such.

My question is: Why I can’t button1:removeEventListener( “tap”, tap ) if in scene:show I added: button1:addEventListener( “tap”, tap )?

PS. Thanks for all your help.

Where is button1 defined?  Where is the “tap” function defined?

Function “tap” is in the main chunk and button1 is defined in scene:create

Refresh

Can you post more code?  Please use the <> button in the edit bar to paste your code in.

Rob

All my code

local composer = require( "composer" ) local json = require "json" local scene = composer.newScene() local myGridlvl1 local myGrid2lvl1 local myCircle1 local button1 local timer1 local function down (event) myCircle1.y = myCircle1.y + 0 end local function movelevel1(event) myGridlvl1.x = myGridlvl1.x - 4 myGrid2lvl1.x = myGrid2lvl1.x - 4 end local function tap (event) myCircle1.y = myCircle1.y - 20 end function endGamelevel1() local endtext1 = display.newText ("You lost!", 160, 50, font, 32) endtext1:setFillColor (0,0,0) timer.cancel(timer1) Runtime:removeEventListener( "enterFrame", onUpdatelevel1 ) Runtime:removeEventListener( "enterFrame", down ) Runtime:removeEventListener( "enterFrame", movelevel1 ) myCircle1:removeEventListener("collision", myCircle1) button1:removeEventListener( "tap", tap ) local function restart (event) composer.gotoScene( "restart1" ) end local restartbutton1 = display.newImage("restart.png", 150, 200, 100, 100) restartbutton1:addEventListener( "tap", restart ) end local function Collision(self, event) if (event.phase == "began") then if (self.ID == "Circle1" and event.other.ID == "Crash1") then endGamelevel1() end end end local function level2 (event) Runtime:removeEventListener( "enterFrame", onUpdatelevel1 ) Runtime:removeEventListener( "enterFrame", down ) Runtime:removeEventListener( "enterFrame", movelevel1 ) myCircle1:removeEventListener("collision", myCircle1) button1:removeEventListener( "tap", tap ) composer.gotoScene("tolvl2") end local function onUpdatelevel1 (event) if (myGridlvl1.x \< 100) then myGridlvl1.x = 160 if (myGrid2lvl1.x \< 100) then myGrid2lvl1.x = 160 end end end function scene:create( event ) local sceneGroup = self.view physics.start() physics.pause() display.setStatusBar( display.HiddenStatusBar ) button1 = display.newImage("button.png", 0, 200, 1000, 1000) local physics = require "physics" physics.setGravity( 0, 0 ) local backgroundlevel1 = display.newImage("backgroundlevel1.png", 160, 240, 500, 600) myCircle1 = display.newImage( "circle.png", 90, 225, 35 ) myCircle1:scale( 0.25, 0.25 ) myCircle1.ID = "Circle1" local myTable = { ["myCircle1PositionY"] = myCircle1.y, } physics.addBody( myCircle1, {radius=38.5} ) myCircle1.collision = Collision myGridlvl1 = display.newRect (160, 100, 1000, 22) myGridlvl1:setFillColor (0,0,0) myGrid2lvl1 = display.newRect (160, 350, 1000, 22) myGrid2lvl1:setFillColor (0,0,0) myGridlvl1.ID = "Crash1" myGrid2lvl1.ID = "Crash1" physics.addBody( myGridlvl1, "static") physics.addBody( myGrid2lvl1, "static") myCircle1:toFront() button1:toFront() local sceneGroup = display.newGroup(button1, backgroundlevel1, myCircle1, myGridlvl1, myGrid2lvl1) end function scene:show( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then composer.removeHidden() elseif ( phase == "did" ) then Runtime:addEventListener( "enterFrame", onUpdatelevel1 ) Runtime:addEventListener( "enterFrame", down ) Runtime:addEventListener( "enterFrame", movelevel1 ) myCircle1:addEventListener("collision", myCircle1) button1:addEventListener( "tap", tap ) physics.start() timer1 = timer.performWithDelay( 5000, level2) end end function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then physics.stop() local jsonSaveData = json.encode( myTable ) local path = system.pathForFile( "myCircle1Position.txt", system.DocumentsDirectory ) local file = io.open( path, "w" ) file:write( jsonSaveData ) io.close( file ) file = nil elseif ( phase == "did" ) then composer.removeHidden() end end function scene:destroy( event ) local sceneGroup = self.view sceneGroup:remove() display.remove( button1 ) display.remove( backgroundlevel1 ) display.remove( myCircle1 ) display.remove( myGridlvl1 ) display.remove( myGrid2lvl1 ) display.remove( endtext1 ) display.remove( restartbutton1 ) end scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) return scene

There are quite a few things that need fixed in this code.  I’ve made some changes and put in comments explaining why I changed the things I did.

local composer = require( "composer" ) local json = require "json" -- -- Do your requires at the top unless there is a good reason to not need it defined until later. -- local physics = require "physics" local scene = composer.newScene() local myGridlvl1 local myGrid2lvl1 local myCircle1 local button1 local timer1 -- -- Indent your code. It helps you line up your "end"s with their function/if/while/repeat's. -- local function down (event) myCircle1.y = myCircle1.y + 0 end local function movelevel1(event) myGridlvl1.x = myGridlvl1.x - 4 myGrid2lvl1.x = myGrid2lvl1.x - 4 end local function tap (event) myCircle1.y = myCircle1.y - 20 end function endGamelevel1() local endtext1 = display.newText ("You lost!", 160, 50, font, 32) endtext1:setFillColor (0,0,0) timer.cancel(timer1) Runtime:removeEventListener( "enterFrame", onUpdatelevel1 ) Runtime:removeEventListener( "enterFrame", down ) Runtime:removeEventListener( "enterFrame", movelevel1 ) myCircle1:removeEventListener("collision", myCircle1) button1:removeEventListener( "tap", tap ) local function restart (event) composer.gotoScene( "restart1" ) end local restartbutton1 = display.newImage("restart.png", 150, 200, 100, 100) restartbutton1:addEventListener( "tap", restart ) end local function Collision(self, event) if (event.phase == "began") then if (self.ID == "Circle1" and event.other.ID == "Crash1") then endGamelevel1() end end end local function level2 (event) Runtime:removeEventListener( "enterFrame", onUpdatelevel1 ) Runtime:removeEventListener( "enterFrame", down ) Runtime:removeEventListener( "enterFrame", movelevel1 ) myCircle1:removeEventListener("collision", myCircle1) button1:removeEventListener( "tap", tap ) composer.gotoScene("tolvl2") end local function onUpdatelevel1 (event) if (myGridlvl1.x \< 100) then myGridlvl1.x = 160 if (myGrid2lvl1.x \< 100) then myGrid2lvl1.x = 160 end end end function scene:create( event ) local sceneGroup = self.view physics.start() physics.pause() -- -- This really should be in main.lua and not in the scene file unless you want to hide the -- the status bar just for this level. If that's the case, move this to the "did" phase of scene:show() -- display.setStatusBar( display.HiddenStatusBar ) -- get in the habit of creating things background to foreground -- it will have you difficulty in the end. -- -- display.newImage takes two number paramters, a x and y to draw the image. -- It draws it at full size. If you want to size it, you have to use :scale() to adjust it. -- If you want to specify the width and height, you want to use display.newImageRect() -- Do you really want it to be a 600 x 500 image? --local backgroundlevel1 = display.newImage("backgroundlevel1.png", 160, 240, 500, 600) local backgroundlevel1 = display.newImage("backgroundlevel1.png", 160, 240) -- again, you can't specify a width and height to display.newImage(). Do you really want the button to be -- 1000 x 1000? How big is your content are in config.lua? -- --button1 = display.newImage("button.png", 0, 200, 1000, 1000) button1 = display.newImage("button.png", 0, 200) -- you have to require physics before you use it and you've already called physics.start() and physics.pause() -- move this to the top.... -- local physics = require "physics" physics.setGravity( 0, 0 ) -- -- This time it looks like you're trying to use the paramters for display.newCircle() to load an image -- -- myCircle1 = display.newImage( "circle.png", 90, 225 ) myCircle1 = display.newImage( "circle.png", 90, 225, 35 ) myCircle1:scale( 0.25, 0.25 ) myCircle1.ID = "Circle1" local myTable = { ["myCircle1PositionY"] = myCircle1.y, } physics.addBody( myCircle1, {radius=38.5} ) myCircle1.collision = Collision myGridlvl1 = display.newRect (160, 100, 1000, 22) myGridlvl1:setFillColor (0,0,0) myGrid2lvl1 = display.newRect (160, 350, 1000, 22) myGrid2lvl1:setFillColor (0,0,0) myGridlvl1.ID = "Crash1" myGrid2lvl1.ID = "Crash1" physics.addBody( myGridlvl1, "static") physics.addBody( myGrid2lvl1, "static") myCircle1:toFront() button1:toFront() -- -- sceneGroup is created above. You just need to insert your items into it -- -- you can do them all at the end like this, or you can insert them as you create them. -- order matters here. Insert the background first. -- -- if you've inserted things in the group properly you won't need to do toFront() calls. -- it also helps to create things in the order they belong. -- sceneGroup:insert(backgroundlevel1) sceneGroup:insert(myCircle1) sceneGroup:insert(myGridlvl1) sceneGroup:insert(myGrid2lvl1) -- local sceneGroup = display.newGroup(button1, backgroundlevel1, myCircle1, myGridlvl1, myGrid2lvl1) end function scene:show( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then composer.removeHidden() elseif ( phase == "did" ) then Runtime:addEventListener( "enterFrame", onUpdatelevel1 ) Runtime:addEventListener( "enterFrame", down ) Runtime:addEventListener( "enterFrame", movelevel1 ) myCircle1:addEventListener("collision", myCircle1) button1:addEventListener( "tap", tap ) physics.start() timer1 = timer.performWithDelay( 5000, level2) end end function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if ( phase == "will" ) then physics.stop() local jsonSaveData = json.encode( myTable ) local path = system.pathForFile( "myCircle1Position.txt", system.DocumentsDirectory ) local file = io.open( path, "w" ) file:write( jsonSaveData ) io.close( file ) file = nil elseif ( phase == "did" ) then composer.removeHidden() end end function scene:destroy( event ) local sceneGroup = self.view --[[-- no need to do this. If these objects have been inserted into the scene's view group -- they will clean up on their own. -- sceneGroup:remove() display.remove( button1 ) display.remove( backgroundlevel1 ) display.remove( myCircle1 ) display.remove( myGridlvl1 ) display.remove( myGrid2lvl1 ) display.remove( endtext1 ) display.remove( restartbutton1 ) --]] end scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) return scene

I never got the error you got, but I did get errors for missing image files (which I had to create).  If you use this code and you’re getting errors, make sure you have all your image files in the folder with your main.lua.

Rob

Sorry, I must explain something.

Error instruction:

  1. Click “Play”

  2. Tap few times. Ball must touch the line.

  3. Click “Restart”

We can’t debug your whole app for you.  If you’re getting an object that’s nil you will need to trace your code and find out why. 

Rob

Can anybody help?

Can you help only in that problem? I’m desperate

Really looks like you need to post more code than you are. You’re asking for help on code which appears to be breaking but only posting fragments.