can't sceneGroup.remove sound files, Image-Sheets,physics.

I know i have to insert any created object to the scenceGroup to be able to let the composer remove it at the exit of the scene . and i able to do that with normal objects like background and images … but when i am trying to insert the soundFiles in the sceneGroup i always got errors also same happen with Image-Sheets .

now when i try to move from Scene to another ( level1 ) to GameOver or Menu . i still see the effect of the physics even when i removed the  images related to them . also the sound still playing . and i got a black screen .

i tried to nil them and display.remove them  but nothing help .

i have another 2 scenes ( Credits and Settings ) and when i go between them and the main menu scene it works perfectly because i am able to insert and remove Objects ( just some images as buttons )  and composer can see and remove them without issue

i suspect i have to add some objects to tables but is that also have to be with soundFiles . ?

So how can i manage that .

here is the code for level1

local composer = require( "composer" ) local scene = composer.newScene() -- ----------------------------------------------------------------------------------------------------------------- -- All code outside of the listener functions will only be executed ONCE unless "composer.removeScene()" is called. -- ----------------------------------------------------------------------------------------------------------------- -- local forward references should go here display.setStatusBar(display.HiddenStatusBar) local physics = require("physics") physics.start() local soundPLay = false local Bats = {}  -- table for the Enemies Bats spawned from top down local options = {     effect = "slideDown",     time = 800, } local sequences\_animatedBat = {         -- consecutive frames sequence         {                 name = "normalRun",                 frames = {1,2,3},                 time = 500,                 loopCount = 0,                 loopDirection = "forward"         },         {                 name = "falldown",                 frames = {4},                 time = 500,                 loopCount = 0,                 loopDirection = "forward"         }, } local sheetOptions = {         width = 80,         height = 75,         numFrames = 5 } local sheet\_animatedBat = graphics.newImageSheet( "BatDownRun.png", sheetOptions ) local soundFile = audio.loadStream ("MainMusicGame.ogg") local soundFile2 = audio.loadSound ("BatHit.ogg") local ScoreToGameOver=0 local score=0 local sequences\_animatedSound = {                 {                 name = "mute",                 frames = {1},                 time = 500,                           loopDirection = "forward"         },                   {                 name = "play",             frames = {2},                 time = 500,                              loopDirection = "forward"          }, } local sheetOptionsSound = {         width = 30,         height = 30,         numFrames = 2 } local sheet\_animatedSound = graphics.newImageSheet( "AnimatedSound.png", sheetOptionsSound )          local function onCollision( event )         if ( event.phase == "began" ) then             print (ScoreToGameOver)             system.vibrate()             ScoreToGameOver = ScoreToGameOver + 1             --ScoreToGameOver.text = ScoreToGameOver         elseif ( event.phase == "ended" ) then           end         end local function GoBack (event)     composer.gotoScene ("menu", options)     return true         -- body end local function tapListenerStopMusic  ( event ) -- here we have to add the tap function                      if   soundPLay  == true then              audio.resume ()              soundPLay = false         animatedSound:setSequence("play")         elseif soundPLay == false then              audio.pause ()              soundPLay = true              animatedSound:setSequence("mute")                       end      end -- ------------------------------------------------------------------------------- -- "scene:create()"     function scene:create( event )     local sceneGroup = self.view     -- Initialize the scene here.     -- Example: add display objects to "sceneGroup", add touch listeners, etc. local score=0 local GoBackButton = display.newImage( "BackButton.png" ) GoBackButton.x=centerX GoBackButton.y=centerY+200 GoBackButton:addEventListener("tap", GoBack) sceneGroup:insert(GoBackButton) animatedSound = display.newSprite( sheet\_animatedSound, sequences\_animatedSound ) animatedSound.x=screenRight-20; animatedSound.y=screenTop+20; sceneGroup:insert(animatedSound) animatedSound:addEventListener ( "tap",tapListenerStopMusic ) local background1 = display.newImage ("FullBackGround.jpg") background1.x = centerX background1.y = centerY -100 background1.width = display.contentWidth\*2 background1.height = display.contentHeight \*2     sceneGroup:insert(background1) background1:toBack();   --transition.to (  background1, {time=12000,alpha=0.2 } ) local  scoreText = display.newText(score,screenLeft+20,screenTop+20, native.systemFontBold, 30) scoreText:setTextColor(1, 0.6, 0.09)   sceneGroup:insert(scoreText)    Base = display.newRect(screenWidth, screenBottom-100, 600, 2) physics.addBody( Base, "static", {isSensor = true } ) sceneGroup:insert(Base) local function tapListener  ( event ) -- here we have to add the tap function         TheBats = event.target                  if TheBats.sequence == "normalRun"  then         TheBats:setSequence("falldown")         TheBats:play()         audio.play (soundFile2)         transition.to ( TheBats, {time=500,x=centerX,y=centerY,alpha=0} )                  score = score + 1         scoreText.text = score         timer.performWithDelay(500,function() TheBats:removeSelf() end )         sceneGroup:insert(scoreText)                 elseif         TheBats.sequence == "falldown" then         TheBats:removeEventListener ( "tap" , tapListener)                      return true     end      end   local function spawnBats()      for i= 1,1 do            Bats[i] =  display.newSprite( sheet\_animatedBat, sequences\_animatedBat );      Bats[i].y= 0      Bats[i].x  =  150      Bats[i]:play()      sceneGroup:insert(Bats[i])            Bats[i].name = "TheBats"      physics.addBody( Bats[i], "dynamic" ,{friction = 1} ,{isSensor = true })      transition.to ( Bats[i], {time=2500,x=150,y=600} )      Bats[i]:addEventListener( "collision", onCollision )      Bats[i]:addEventListener ( "tap",tapListener)        end end local function GameOverNext( event)    if score == 3  then     composer.gotoScene ("GameOver")     return true      end end timer.performWithDelay(3000, spawnBats,12 ) Runtime:addEventListener( "enterFrame", GameOverNext ) Base:addEventListener( "collision", onCollision ) end -- "scene:show()" function scene:show( event )     local sceneGroup = self.view     local phase = event.phase if ( phase == "will" ) then         -- Called when the scene is still off screen (but is about to come on screen). --sceneGroup:insert(sheetOptionsSound) --sceneGroup:insert(sheet\_animatedSound) --sceneGroup:insert(scoreText) --sceneGroup:insert(sequences\_animatedSound) --sceneGroup:insert(soundFile2) --sceneGroup:insert(sheetOptions)   --sceneGroup:insert(sheet\_animatedBat) --sceneGroup:insert(sequences\_animatedBat) --sceneGroup:insert(animatedSound)  elseif ( phase == "did" ) then         -- Called when the scene is now on screen.         -- Insert code here to make the scene come alive.         -- Example: start timers, begin animation, play audio, etc. audio.play(soundFile)   local ads = require(  "ads"  )         bannerAppID = "ca-app-pub-xxx"   --for your Android banner         interstitialAppID = "ca-app-pub-xxx" --for your Android interstitial --end local adProvider = "admob" ads.init( adProvider, "ca-app-pub-xxx", adListener ) ads.show( "banner", { x=0, y=100000 } ) --sceneGroup:insert(adProvider) if ( ads.isLoaded("interstitial") ) then             ads.show( "interstitial", { appId=interstitialAppID } ) end end end -- "scene:hide()" function scene:hide( event )     local sceneGroup = self.view     local phase = event.phase     if ( phase == "will" ) then         -- Called when the scene is on screen (but is about to go off screen).         -- Insert code here to "pause" the scene.         -- Example: stop timers, stop animation, stop audio, etc.     elseif ( phase == "did" ) then         -- Called immediately after scene goes off screen.     end end -- "scene:destroy()" function scene:destroy( event )     local sceneGroup = self.view     -- Called prior to the removal of scene's view ("sceneGroup").     -- Insert code here to clean up the scene.     -- Example: remove display objects, save state, etc. local sheet\_animatedBat=nil local sheet\_animatedSound=nil local soundFile=nil local soundFile2=nil display.remove( soundFile ) display.remove(soundFile2) display.remove(sheet\_animatedSound) display.remove(sheet\_animatedBat) -- is a faster way of doing this: for i= 1,1 do     Bats[i]:removeSelf() end             TheBats:removeSelf() sceneGroup.remove(spawnBats) sceneGroup.remove(animatedSound) sceneGroup.remove(background1) sceneGroup.remove(scoreText) sceneGroup.remove(Base) sceneGroup.remove(Bats[i]) composer.removeScene( "Level1",true ) composer.removeScene( "main" ) composer.removeScene( "menu" ) end -- ------------------------------------------------------------------------------- -- Listener setup scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) -- ------------------------------------------------------------------------------- return scene

The scene’s view group is a “display.newGroup”.  Notice it’s a “display.*” API call.  You can only add “display.*” objects to display.newGroup()'s.

Sounds, image sheets (graphics.*) and such are not display objects and cannot be inserted into a display.newGroup().

Rob

Thanks @Rob for the info .

but still i cant successfully able to move from Level1 to another scene and remove all objects attached to that scene include Sounds , images sheets and physics.

can you help with the code to tell me if it is correct or i am doing something wrong .

If you create an object within a function, it will only exist within that function. This means that every local variable you create in scene:create will only exist in that block of code. You won’t be able to access them in other functions, such as scene:destroy. Additionally, when setting a variable to nil, you don’t need to add local keyword at the beginning, assuming the variable has already been created. I hope this helps.

Thanks @jjsanchezramirez

actually i tried only declaring the variable as global ( removing local at the front )  before in the destroy scene and still not working …

any help

Can you post your latest code?

Globals are not the way to go.  Ordering your code correctly is they way to handle properly.  Follow the simple rule:  you have to define it before you can use it.

local ball local function moveBall()       ball.x = ball.x + 100       ball.y = ball.y + 50 end function scene:create( event )     local sceneGroup = self.view physics.start() physics.pause()     ball = display.newCiricle( 10, 10, 25 )  -- note no "local" here.  We defined it "local" at the top     sceneGroup:insert( ball )  -- must be in sceneGroup to be managed physics:addBody( ball, "static", { radius = 25 }) end function scene:show( event )     if event.phase == "did" then physics.start()          moveBall()     end end function scene:hide( event )     if event.phase == "will" then          physics.pause()     end end

In this case we need to use ball in different functions.  We need to create it in scene:create().  We need to move it after the scene is on the screen.   We declare ball at the top as a local variable to the entire module but we don’t create it.   It’s now scoped where any function or if-then-else or for-do-end block can see it.  Next we create a single function moveBall() that can access “ball” since it’s defined at a higher block than the moveBall function.  Also, the function is being defined before we ever call it.  It’s not inside another function.  Just like our “local ball” makes ball available to the entire module, the function moveBall is local to the entire module too and any code after it can call it.

We then inside scene:create() actually create the ball and put it in ball variable.  Then we make sure the ball is going to be managed by Composer with the sceneGroup:insert( ball ) line.

Finally in scene:show() you see where we call moveBall() after the scene is transitioned on the screen.  Now in this simple example, you probably won’t see the ball move because it’s going to happen too quickly.    This is how you have to organize your code.

Physics

As far as physics goes, you have to call physics.start() before you can add bodies, however you don’t want the bodies to start moving until the scene is on the screen.  As you see above I call physics.start() in scene:create() but I immediately pause it.  This will allow me to add physics bodies (as I do with ball) but nothing happens.

In scene:show() just like we move ball once we have transitioned on screen, then we can call physics.start() again to undo the pause and actually start physics for real.

Audio

Audio is a bit trickier to handle.  Some things like beeps, clicks, and such should be created in main.lua and made global if you’re going to be using them over and over and in multiple scenes, or use a sound effects module (much like a data module from: Sounds specific to the scene may be best loaded in scene:show and disposed in scene hide, if the sounds are not very large.

Let me modify the code above to show this:

local ball local bigBoomSound local function moveBall()       ball.x = ball.x + 100       ball.y = ball.y + 50       audio.play( bigBoomSound ) end function scene:create( event )     local sceneGroup = self.view     physics.start()     physics.pause()     ball = display.newCiricle( 10, 10, 25 )  -- note no "local" here.  We defined it "local" at the top     sceneGroup:insert( ball )  -- must be in sceneGroup to be managed     physics:addBody( ball, "static", { radius = 25 }) end function scene:show( event )     if event.phase == "did" then          physics.start()          moveBall()     else -- event.phase is "will"         bigBoomSound = audio.loadSound( "bigboom.wav" )     end end function scene:hide( event )     if event.phase == "will" then          physics.pause()     else -- phase == did          audio.dispose( bigBoomSound )     end end

If the sounds are larger, perhaps load them in scene:create() and dispose them in scene:destroy(), but you have to dispose them yourself.

Image Sheets

These don’t need to be disposed of.  Frequently they will be local to some function and will go away when the function exits.

Hope this helps you understand how to handle all of this.

Rob

Thanks for your advices @ Rob

i already done some modifications and for testing only i am  trying  now with one bat ( enemy ) only

and i was able to fix the audio issue by using audio,stop(1) , moving from scene to another work great except

that now i am facing 2 issues which i guess it could help others too

1- i have a listener that wait till the score reach  number and then go to the next scene but :

if i use Runtime:addEventListener( “enterFrame”, Func)  it work fine but when it go to the next scene it just make a black screen and freeze . so how can  i always wait for an even to happen without using the RunTimeEventLisnter ?

2-  when i tried to use a collision to fire a game over ( if the bat reach a line down in the screen )

it always fire the collision twice with both the bat and the line and i am not able to build an if statement for the result

here is the printed result for the objects

1
Bat1
Base
2
Bat1
Base

.

i tried to use return true with no help

here is the new code

local composer = require( "composer" ) local scene = composer.newScene() physics = require("physics") -- ----------------------------------------------------------------------------------------------------------------- -- All code outside of the listener functions will only be executed ONCE unless "composer.removeScene()" is called. -- ----------------------------------------------------------------------------------------------------------------- -- local forward references should go here display.setStatusBar(display.HiddenStatusBar) local soundPLay = false local MainSound local BatsClicks local ScoreToGameOver local Bat1 local score local scoreText local sheet\_animatedBat local sheet\_animatedSound -----------------Local Animated Sheets ----------------------------- local options = { effect = "slideDown", time = 800, } local sequences\_animatedBat = { -- consecutive frames sequence { name = "normalRun", frames = {1,2,3}, time = 500, loopCount = 0, loopDirection = "forward" }, { name = "falldown", frames = {4}, time = 500, loopCount = 0, loopDirection = "forward" }, } local sheetOptions = { width = 80, height = 75, numFrames = 5 } local sequences\_animatedSound = { { name = "mute", frames = {1}, time = 500, loopDirection = "forward" }, { name = "play", frames = {2}, time = 500, loopDirection = "forward" }, } local sheetOptionsSound = { width = 30, height = 30, numFrames = 2 } local function onLocalCollision( self,event ) if ( event.phase == "began" ) then system.vibrate() Runtime:removeEventListener("collision", onLocalCollision) ScoreToGameOver = ScoreToGameOver +1 print (ScoreToGameOver) print( event.target.myName ) --the first object in the collision print( event.other.myName ) return true elseif ( event.phase == "ended" ) then end end local function tapListenerStopMusic ( event ) -- here we have to add the tap function if soundPLay == true then audio.resume () soundPLay = false animatedSound:setSequence("play") elseif soundPLay == false then audio.pause () soundPLay = true animatedSound:setSequence("mute") end end local function tapListener ( event ) -- here we have to add the tap function --Bat1 = event.target if Bat1.sequence == "normalRun" then Bat1:setSequence("falldown") Bat1:play() audio.play (BatsClicks) --transition.to ( Bat1, {time=500,x=centerX,y=centerY,alpha=0} ) score = score + 1 scoreText.text = score --timer.performWithDelay(100,function() Bat1:removeSelf() end ) elseif Bat1.sequence == "falldown" then Bat1:removeEventListener ( "tap" , tapListener) return true end end local function MoveBat1() transition.to ( Bat1, {time=2500,x=150,y=600} ) end local function GameOverNext( event) if ScoreToGameOver==2 then composer.gotoScene ("GameOver") return true end end local function GoBack (event) composer.gotoScene ("GameOver") return true -- body end local function playSound( ) audio.play( MainSound ) end -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- "scene:create()" function scene:create( event ) local sceneGroup = self.view -- Initialize the scene here. -- Example: add display objects to "sceneGroup", add touch listeners, etc. physics.start() physics.pause() physics.setGravity( 0, 0 ) sheet\_animatedBat = graphics.newImageSheet( "BatDownRun.png", sheetOptions ) sheet\_animatedSound = graphics.newImageSheet( "AnimatedSound.png", sheetOptionsSound ) background1 = display.newImage ("FullBackGround.jpg") background1.x = centerX background1.y = centerY -100 background1.width = display.contentWidth\*2 background1.height = display.contentHeight \*2 sceneGroup:insert(background1) background1:toBack() score=0 ScoreToGameOver=0 Bat1 = display.newSprite( sheet\_animatedBat, sequences\_animatedBat ) Bat1.myName="Bat1" Bat1.y= 0 Bat1.x = 150 Bat1:play() physics.addBody( Bat1, "dynamic" ,{friction = 0} ,{isSensor = true }) sceneGroup:insert(Bat1) Bat1.collision = onLocalCollision Bat1:addEventListener( "collision", Bat1 ) Bat1:addEventListener ( "tap",tapListener) GoBackButton = display.newImage( "BackButton.png" ) GoBackButton.x=centerX GoBackButton.y=centerY+200 GoBackButton:addEventListener("tap", GoBack) sceneGroup:insert(GoBackButton) animatedSound = display.newSprite( sheet\_animatedSound, sequences\_animatedSound ) animatedSound.x=screenRight-20; animatedSound.y=screenTop+20; sceneGroup:insert(animatedSound) animatedSound:addEventListener ( "tap",tapListenerStopMusic ) --transition.to ( background1, {time=12000,alpha=0.2 } ) scoreText = display.newText(score,screenLeft+20,screenTop+20, native.systemFontBold, 30) scoreText:setTextColor(1, 0.6, 0.09) sceneGroup:insert(scoreText) Base = display.newLine(0,300,600,300) Base.myName="Base" physics.addBody( Base, "static", {isSensor = true } ) sceneGroup:insert(Base) --Base.collision = onLocalCollision2 --Base:addEventListener( "collision", Base ) end -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- "scene:show()" function scene:show( event ) local sceneGroup = self.view local phase = event.phase -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- if ( phase == "will" ) then -- Called when the scene is still off screen (but is about to come on screen). --Runtime:addEventListener( "enterFrame", GameOverNext ) MainSound = audio.loadSound ("MainMusicGame.ogg") BatsClicks = audio.loadSound ("BatHit.ogg") -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- elseif ( phase == "did" ) then -- Called when the scene is now on screen. -- Insert code here to make the scene come alive. -- Example: start timers, begin animation, play audio, etc. audio.play(MainSound) physics.start() --timer.performWithDelay(9000, GameOverNext) timer.performWithDelay(3000, MoveBat1) local ads = require( "ads" ) bannerAppID = "ca-app-pub-xxx" --for your Android banner interstitialAppID = "ca-app-pub-xxx" --for your Android interstitial --end local adProvider = "admob" ads.init( adProvider, "ca-app-pub-xxx", adListener ) ads.show( "banner", { x=0, y=100000 } ) if ( ads.isLoaded("interstitial") ) then ads.show( "interstitial", { appId=interstitialAppID } ) end end end -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- "scene:hide()" function scene:hide( event ) local sceneGroup = self.view local phase = event.phase -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- if ( phase == "will" ) then -- Called when the scene is on screen (but is about to go off screen). -- Insert code here to "pause" the scene. -- Example: stop timers, stop animation, stop audio, etc.. audio.stop(1) audio.dispose( MainSound ) audio.dispose(BatsClicks) -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- elseif ( phase == "did" ) then -- Called immediately after scene goes off screen. audio.dispose( MainSound ) audio.dispose(BatsClicks) physics.pause() end end -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- "scene:destroy()" function scene:destroy( event ) local sceneGroup = self.view -- Called prior to the removal of scene's view ("sceneGroup"). -- Insert code here to clean up the scene. -- Example: remove display objects, save state, etc. -- is a faster way of doing this: ------ forget about these i already used composer.recycleOnSceneChange = true --------- --Bat1:removeSelf() --sceneGroup.remove(background1) --sceneGroup.remove(scoreText) --sceneGroup.remove(Base) --sceneGroup.remove(Bat1) --composer.removeScene( "Level1",true ) end -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- Listener setup scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) -- ------------------------------------------------------------------------------- return scene

ok i fixed the multi-fire collision by use radius=0 for Bat1 (enemy )

i am still working on the second issue i will update soon

ok fixed the Runtime:addEventListener( “enterFrame”, GameOverNext ) by removing it later in the hide phase :slight_smile:

The scene’s view group is a “display.newGroup”.  Notice it’s a “display.*” API call.  You can only add “display.*” objects to display.newGroup()'s.

Sounds, image sheets (graphics.*) and such are not display objects and cannot be inserted into a display.newGroup().

Rob

Thanks @Rob for the info .

but still i cant successfully able to move from Level1 to another scene and remove all objects attached to that scene include Sounds , images sheets and physics.

can you help with the code to tell me if it is correct or i am doing something wrong .

If you create an object within a function, it will only exist within that function. This means that every local variable you create in scene:create will only exist in that block of code. You won’t be able to access them in other functions, such as scene:destroy. Additionally, when setting a variable to nil, you don’t need to add local keyword at the beginning, assuming the variable has already been created. I hope this helps.

Thanks @jjsanchezramirez

actually i tried only declaring the variable as global ( removing local at the front )  before in the destroy scene and still not working …

any help

Can you post your latest code?

Globals are not the way to go.  Ordering your code correctly is they way to handle properly.  Follow the simple rule:  you have to define it before you can use it.

local ball local function moveBall()       ball.x = ball.x + 100       ball.y = ball.y + 50 end function scene:create( event )     local sceneGroup = self.view physics.start() physics.pause()     ball = display.newCiricle( 10, 10, 25 )  -- note no "local" here.  We defined it "local" at the top     sceneGroup:insert( ball )  -- must be in sceneGroup to be managed physics:addBody( ball, "static", { radius = 25 }) end function scene:show( event )     if event.phase == "did" then physics.start()          moveBall()     end end function scene:hide( event )     if event.phase == "will" then          physics.pause()     end end

In this case we need to use ball in different functions.  We need to create it in scene:create().  We need to move it after the scene is on the screen.   We declare ball at the top as a local variable to the entire module but we don’t create it.   It’s now scoped where any function or if-then-else or for-do-end block can see it.  Next we create a single function moveBall() that can access “ball” since it’s defined at a higher block than the moveBall function.  Also, the function is being defined before we ever call it.  It’s not inside another function.  Just like our “local ball” makes ball available to the entire module, the function moveBall is local to the entire module too and any code after it can call it.

We then inside scene:create() actually create the ball and put it in ball variable.  Then we make sure the ball is going to be managed by Composer with the sceneGroup:insert( ball ) line.

Finally in scene:show() you see where we call moveBall() after the scene is transitioned on the screen.  Now in this simple example, you probably won’t see the ball move because it’s going to happen too quickly.    This is how you have to organize your code.

Physics

As far as physics goes, you have to call physics.start() before you can add bodies, however you don’t want the bodies to start moving until the scene is on the screen.  As you see above I call physics.start() in scene:create() but I immediately pause it.  This will allow me to add physics bodies (as I do with ball) but nothing happens.

In scene:show() just like we move ball once we have transitioned on screen, then we can call physics.start() again to undo the pause and actually start physics for real.

Audio

Audio is a bit trickier to handle.  Some things like beeps, clicks, and such should be created in main.lua and made global if you’re going to be using them over and over and in multiple scenes, or use a sound effects module (much like a data module from: Sounds specific to the scene may be best loaded in scene:show and disposed in scene hide, if the sounds are not very large.

Let me modify the code above to show this:

local ball local bigBoomSound local function moveBall()       ball.x = ball.x + 100       ball.y = ball.y + 50       audio.play( bigBoomSound ) end function scene:create( event )     local sceneGroup = self.view     physics.start()     physics.pause()     ball = display.newCiricle( 10, 10, 25 )  -- note no "local" here.  We defined it "local" at the top     sceneGroup:insert( ball )  -- must be in sceneGroup to be managed     physics:addBody( ball, "static", { radius = 25 }) end function scene:show( event )     if event.phase == "did" then          physics.start()          moveBall()     else -- event.phase is "will"         bigBoomSound = audio.loadSound( "bigboom.wav" )     end end function scene:hide( event )     if event.phase == "will" then          physics.pause()     else -- phase == did          audio.dispose( bigBoomSound )     end end

If the sounds are larger, perhaps load them in scene:create() and dispose them in scene:destroy(), but you have to dispose them yourself.

Image Sheets

These don’t need to be disposed of.  Frequently they will be local to some function and will go away when the function exits.

Hope this helps you understand how to handle all of this.

Rob

Thanks for your advices @ Rob

i already done some modifications and for testing only i am  trying  now with one bat ( enemy ) only

and i was able to fix the audio issue by using audio,stop(1) , moving from scene to another work great except

that now i am facing 2 issues which i guess it could help others too

1- i have a listener that wait till the score reach  number and then go to the next scene but :

if i use Runtime:addEventListener( “enterFrame”, Func)  it work fine but when it go to the next scene it just make a black screen and freeze . so how can  i always wait for an even to happen without using the RunTimeEventLisnter ?

2-  when i tried to use a collision to fire a game over ( if the bat reach a line down in the screen )

it always fire the collision twice with both the bat and the line and i am not able to build an if statement for the result

here is the printed result for the objects

1
Bat1
Base
2
Bat1
Base

.

i tried to use return true with no help

here is the new code

local composer = require( "composer" ) local scene = composer.newScene() physics = require("physics") -- ----------------------------------------------------------------------------------------------------------------- -- All code outside of the listener functions will only be executed ONCE unless "composer.removeScene()" is called. -- ----------------------------------------------------------------------------------------------------------------- -- local forward references should go here display.setStatusBar(display.HiddenStatusBar) local soundPLay = false local MainSound local BatsClicks local ScoreToGameOver local Bat1 local score local scoreText local sheet\_animatedBat local sheet\_animatedSound -----------------Local Animated Sheets ----------------------------- local options = { effect = "slideDown", time = 800, } local sequences\_animatedBat = { -- consecutive frames sequence { name = "normalRun", frames = {1,2,3}, time = 500, loopCount = 0, loopDirection = "forward" }, { name = "falldown", frames = {4}, time = 500, loopCount = 0, loopDirection = "forward" }, } local sheetOptions = { width = 80, height = 75, numFrames = 5 } local sequences\_animatedSound = { { name = "mute", frames = {1}, time = 500, loopDirection = "forward" }, { name = "play", frames = {2}, time = 500, loopDirection = "forward" }, } local sheetOptionsSound = { width = 30, height = 30, numFrames = 2 } local function onLocalCollision( self,event ) if ( event.phase == "began" ) then system.vibrate() Runtime:removeEventListener("collision", onLocalCollision) ScoreToGameOver = ScoreToGameOver +1 print (ScoreToGameOver) print( event.target.myName ) --the first object in the collision print( event.other.myName ) return true elseif ( event.phase == "ended" ) then end end local function tapListenerStopMusic ( event ) -- here we have to add the tap function if soundPLay == true then audio.resume () soundPLay = false animatedSound:setSequence("play") elseif soundPLay == false then audio.pause () soundPLay = true animatedSound:setSequence("mute") end end local function tapListener ( event ) -- here we have to add the tap function --Bat1 = event.target if Bat1.sequence == "normalRun" then Bat1:setSequence("falldown") Bat1:play() audio.play (BatsClicks) --transition.to ( Bat1, {time=500,x=centerX,y=centerY,alpha=0} ) score = score + 1 scoreText.text = score --timer.performWithDelay(100,function() Bat1:removeSelf() end ) elseif Bat1.sequence == "falldown" then Bat1:removeEventListener ( "tap" , tapListener) return true end end local function MoveBat1() transition.to ( Bat1, {time=2500,x=150,y=600} ) end local function GameOverNext( event) if ScoreToGameOver==2 then composer.gotoScene ("GameOver") return true end end local function GoBack (event) composer.gotoScene ("GameOver") return true -- body end local function playSound( ) audio.play( MainSound ) end -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- "scene:create()" function scene:create( event ) local sceneGroup = self.view -- Initialize the scene here. -- Example: add display objects to "sceneGroup", add touch listeners, etc. physics.start() physics.pause() physics.setGravity( 0, 0 ) sheet\_animatedBat = graphics.newImageSheet( "BatDownRun.png", sheetOptions ) sheet\_animatedSound = graphics.newImageSheet( "AnimatedSound.png", sheetOptionsSound ) background1 = display.newImage ("FullBackGround.jpg") background1.x = centerX background1.y = centerY -100 background1.width = display.contentWidth\*2 background1.height = display.contentHeight \*2 sceneGroup:insert(background1) background1:toBack() score=0 ScoreToGameOver=0 Bat1 = display.newSprite( sheet\_animatedBat, sequences\_animatedBat ) Bat1.myName="Bat1" Bat1.y= 0 Bat1.x = 150 Bat1:play() physics.addBody( Bat1, "dynamic" ,{friction = 0} ,{isSensor = true }) sceneGroup:insert(Bat1) Bat1.collision = onLocalCollision Bat1:addEventListener( "collision", Bat1 ) Bat1:addEventListener ( "tap",tapListener) GoBackButton = display.newImage( "BackButton.png" ) GoBackButton.x=centerX GoBackButton.y=centerY+200 GoBackButton:addEventListener("tap", GoBack) sceneGroup:insert(GoBackButton) animatedSound = display.newSprite( sheet\_animatedSound, sequences\_animatedSound ) animatedSound.x=screenRight-20; animatedSound.y=screenTop+20; sceneGroup:insert(animatedSound) animatedSound:addEventListener ( "tap",tapListenerStopMusic ) --transition.to ( background1, {time=12000,alpha=0.2 } ) scoreText = display.newText(score,screenLeft+20,screenTop+20, native.systemFontBold, 30) scoreText:setTextColor(1, 0.6, 0.09) sceneGroup:insert(scoreText) Base = display.newLine(0,300,600,300) Base.myName="Base" physics.addBody( Base, "static", {isSensor = true } ) sceneGroup:insert(Base) --Base.collision = onLocalCollision2 --Base:addEventListener( "collision", Base ) end -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- "scene:show()" function scene:show( event ) local sceneGroup = self.view local phase = event.phase -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- if ( phase == "will" ) then -- Called when the scene is still off screen (but is about to come on screen). --Runtime:addEventListener( "enterFrame", GameOverNext ) MainSound = audio.loadSound ("MainMusicGame.ogg") BatsClicks = audio.loadSound ("BatHit.ogg") -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- elseif ( phase == "did" ) then -- Called when the scene is now on screen. -- Insert code here to make the scene come alive. -- Example: start timers, begin animation, play audio, etc. audio.play(MainSound) physics.start() --timer.performWithDelay(9000, GameOverNext) timer.performWithDelay(3000, MoveBat1) local ads = require( "ads" ) bannerAppID = "ca-app-pub-xxx" --for your Android banner interstitialAppID = "ca-app-pub-xxx" --for your Android interstitial --end local adProvider = "admob" ads.init( adProvider, "ca-app-pub-xxx", adListener ) ads.show( "banner", { x=0, y=100000 } ) if ( ads.isLoaded("interstitial") ) then ads.show( "interstitial", { appId=interstitialAppID } ) end end end -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- "scene:hide()" function scene:hide( event ) local sceneGroup = self.view local phase = event.phase -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- if ( phase == "will" ) then -- Called when the scene is on screen (but is about to go off screen). -- Insert code here to "pause" the scene. -- Example: stop timers, stop animation, stop audio, etc.. audio.stop(1) audio.dispose( MainSound ) audio.dispose(BatsClicks) -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- elseif ( phase == "did" ) then -- Called immediately after scene goes off screen. audio.dispose( MainSound ) audio.dispose(BatsClicks) physics.pause() end end -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- "scene:destroy()" function scene:destroy( event ) local sceneGroup = self.view -- Called prior to the removal of scene's view ("sceneGroup"). -- Insert code here to clean up the scene. -- Example: remove display objects, save state, etc. -- is a faster way of doing this: ------ forget about these i already used composer.recycleOnSceneChange = true --------- --Bat1:removeSelf() --sceneGroup.remove(background1) --sceneGroup.remove(scoreText) --sceneGroup.remove(Base) --sceneGroup.remove(Bat1) --composer.removeScene( "Level1",true ) end -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------- -- Listener setup scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) -- ------------------------------------------------------------------------------- return scene

ok i fixed the multi-fire collision by use radius=0 for Bat1 (enemy )

i am still working on the second issue i will update soon

ok fixed the Runtime:addEventListener( “enterFrame”, GameOverNext ) by removing it later in the hide phase :slight_smile: