Composer - correctly removing audio/objects/listeners

Hi,

I wonder if anyone can offer any advice - I’m just finishing my first game and the final hurdle is, I think, with Composer.

I want to achieve the following:

main --> start --> game  --> gameover – then the game can be returned to via a button on the gameover screen.

It’s  small, simple game, so I think I have two options to aim for:

  1. when the player restarts the game from gameover, game is rebuilt from scratch. This is what I’d prefer…

  2. reposition and reset game elements when game is restarted.

When I move from the main game to the game over scene using Composer I get ‘nil value’ errors. I’ve tried removing display objects, removing the scene they’re in, and both…

I’m shuffling my code and trying all remedies I can think of… other times I’m getting upvalue errors. From there I removed the Listeners that connected back to functions using those variables and the result was nil values …

I realise this doesn’t mean a lot without the code but it’s quite long. I’m just hoping for any pointers - maybe a link to an example of a lua file using Composer in which elements are removed?  I’ve seen some great tutorials - including the CoronaGeeks 124 video, but I’m not clear how to restart a scene properly, where to cancel and remove things.

Many thanks.

Code would be helpful. You don’t need to post everything, just show us your main game scene and your game over scene. 

Hi James thanks for replying.

Here’s my code - I’ve taken out a few things where I could but this is the gist of it. The game over code is indicated towards the end.

I realise this is long - I’m still learning and I guess my next lesson will be modules.

Since posting my original question I’m a small step closer to repositioning everything just before leaving the game scene - not removing anything - and then having it ready to begin when the player returns. The issue right now is when I try to move the character on returning to the game I get ‘Attempt to call method ‘applyLinearImpulse’ (a nil value)’.

I think the main problem is that the game file is so long and everything has become so interconnected that if I reposition anything I get errors. I know maybe I ought to have put some things in different scene functions… could that be an issue? I’d just like to be able to ‘restart’ the game either by returning to a reinitialised state, or by removing all elements and rebuilding. 

To give you a picture of the game - the player character is Arthur - he’s chased by a squaddie. Arthur either gets caught and it’s game over, or he makes it to the end and succeeds. On the way he collects objects - one shown here is beer. The score is displayed on the end screen (via a myData.lua file to pass the variable).

Many thanks for any help, this is driving me around the bend.

[lua]


– game.lua


display.setStatusBar(display.HiddenStatusBar)

local composer = require( “composer” )

local scene = composer.newScene()

local myData = require( “mydata” )

local physics = require( “physics” )

system.activate( “multitouch” )

physics.start()

physics.pause()

local textureFilter = “nearest”

local screenW, screenH, halfW = display.contentWidth, display.contentHeight, display.contentWidth*0.5

local arthur

local map

local touchright = “yes”

local touchleft = “yes”

local score

local speed

local leftbutton

local rightbutton

local jumpbutton

local framerate = 900

local vx = 0

local vy = 0

local sx = 0

local sy = 0

local canJump = 0

local runsound = audio.loadSound ( “audio/runsound.wav” )

local gameisplaying = 0

local gameover = 0

local dusk = require(“Dusk.Dusk”)

map = dusk.buildMap(“levelgraphic2.json”)

map:scale (1, 1)

map.setTrackingLevel(0.9)

map.setCameraBounds ({ xMin = display.contentCenterX, yMin = display.contentCenterY, xMax = map.data.width - display.contentCenterX, yMax = map.data.height - display.contentCenterY })

map.layer[1].setCameraOffset(14, 24)

map.layer[2].setCameraOffset(14, 24)


function scene:create( event )


local sceneGroup = self.view

----------------------------------------------------------scene management

gui = display.newGroup()

gui.front = display.newGroup()

gui.back = display.newGroup()

gui:insert(gui.back) --map is in here (characters are in map)

gui:insert(gui.front) --buttons

gui.back:insert(map)

sceneGroup:insert(gui)

----------------------------------------------------------Target for level completion

local pubdoor = display.newImageRect( “pubdoor.png”, 40, 55 )

pubdoor.x, pubdoor.y =  map.data.width - 128, 106

physics.addBody( pubdoor, “static” )

pubdoor.id = “pubdoor”

pubdoor.title = “pubdoor”

pubdoor.myName = “pubdoor”

map.layer[1]:insert(pubdoor)

---------------------------------------------------------Player

local sheet1 = graphics.newImageSheet( “arthur.png”, { width=25, height=37, numFrames=14 } )

local arthurData =

{

   { name=“standing”, frames= { 13 } },

   { name=“running”, start=1, count=12, time=framerate },

   { name=“beenhit”, frames= { 14 } }

}

local arthur = display.newSprite( sheet1, arthurData )

arthur.x = 140

arthur.y = 106

arthur.id = “arthur”

arthur.title = “arthur”

arthur.myName = “arthur”

arthur.rotation = 0

arthur.anchorY = 1

arthur.anchorX = 0.5

arthur:setSequence(“standing”)

arthur:play()

physics.addBody( arthur, “dynamic”, { density=0.9, friction=0.5, bounce=0} )

arthur.isFixedRotation = true

map.layer[1]:insert(arthur)

-------------------------------check for movement and set correct animation for player

local function motioncheck (vx)

local current_sequence = arthur.sequence

if vx > 1.5 then

if current_sequence == “running” then

return true

else 

arthur:setSequence( “running” )

arthur:play()

end

end

if vx <= 1.5 then

if current_sequence == “standing” then

return true

else

arthur:setSequence(“standing”)

arthur:play()

end

end

end

---------------------------------------------------------------Create Squaddie 

local sheet2 = graphics.newImageSheet( “squaddie.png”, { width=25, height=37, numFrames=16 } )

local squaddieData =

{

   { name=“running”, start=1, count=12, time=framerate },

   { name=“punch”, start=14, count=3, time=500, loopCount =1 }

}

local squaddie = display.newSprite( sheet2, squaddieData)

squaddie.x = -10

squaddie.y = 105

squaddie.id = “squaddie”

squaddie.title = “squaddie”

squaddie.myName = “squaddie”

squaddie:setSequence(“running”)

squaddie:play()

physics.addBody( squaddie, “dynamic”, { density=2, friction=1, bounce=0.0  } )

squaddie.isFixedRotation = true

map.layer[1]:insert(squaddie)

----------------------------------------------------Graphics at the top of the screen

------BEER---------

local beerGlimmer = display.newImageRect( “glimmer.png”, 35, 35 )

beerGlimmer.anchorX = 0.5

beerGlimmer.anchorY = 0.5

beerGlimmer.xScale = 2

beerGlimmer.yScale = 2

beerGlimmer.x, beerGlimmer.y =  (screenW/10) * 7,  20

gui.front:insert(beerGlimmer)

local sheet3 = graphics.newImageSheet( “beerweb.png”, { width=12, height=12, numFrames=6, sheetContentWidth=72, sheetContentHeight=12} )

local beerData =

{

  { name=“beerpause”, frames = {1}, time=3000, loopCount =1},

  { name=“beershining”, frames = {2,3,4,5,6}, time=300, loopCount =1 }

}

local beer = display.newSprite( sheet3, beerData )

beer.x = (screenW/10) * 7

beer.y = 20

beer:setSequence(“beerpause”)

beer:play()

gui.front:insert(beer)

local function beerListener( event ) 

local beer_sequence = beer.sequence

if ( event.phase == “ended” ) and beer_sequence == “beerpause” then

local beerData = target

  beer:setSequence( “beershining” )

  beer:play()

elseif ( event.phase == “ended” ) and beer_sequence == “beershining” then

local beerData = target

  beer:setSequence( “beerpause” )

  beer:play()

  end

end

local function spinBeerGlimmer (event)

transition.to( beerGlimmer, { rotation = beerGlimmer.rotation-360, time=4000, onComplete=spinBeerGlimmer } )

end

-------------------------------------------display number of collected items

local beerscoretext = display.newText( “” , ((screenW/10) * 7)+3, 44, native.systemFont, 14 )

beerscoretext:setFillColor( 1, 1, 1 )

beerscoretext.align = “center”

gui.front:insert(beerscoretext)

------------------------------------------Collectables that float in

---- collectable beer-------

local collectablebeer = display.newSprite( sheet3, beerData )

collectablebeer:setSequence(“beershining”)

collectablebeer.collected = 0

collectablebeer:play()

collectablebeer.x = 350

collectablebeer.y = math.random (32, 96)

map.layer [1]:insert(collectablebeer)

physics.addBody( collectablebeer, “static”, { density=0.1, friction=1, bounce=0.0, radius = 5  } )

collectablebeer.isFixedRotation = true

collectablebeer.speed = 0

collectablebeer.initY = collectablebeer.y

collectablebeer.amp = math.random(5,32)

collectablebeer.angle = math.random (1, 360)

collectablebeer.myName = “collectablebeer”

local function collectablebeerListener( event ) 

local collectablebeer_sequence = collectablebeer.sequence

if ( event.phase == “ended” ) and collectablebeer_sequence == “beerpause” then

local collectablebeerData = target

  collectablebeer:setSequence( “beershining” )

  collectablebeer:play()

elseif ( event.phase == “ended” ) and collectablebeer_sequence == “beershining” then

local collectablebeerData = target

  collectablebeer:setSequence( “beerpause” )

  collectablebeer:play()

  end

end

collectablebeer:addEventListener( “sprite”, collectablebeerListener )

function scrollcollectbeer (self, event)

if self.x < (arthur.x-200) then

self.x = (arthur.x + 200)

else

if collectablebeer.collected == 0 then

self.x = self.x - self.speed

self.angle = self.angle + 0.1

self.y = self.amp * math.sin(self.angle) + self.initY

end

end

end

collectablebeer.enterFrame = scrollcollectbeer

Runtime:addEventListener(“enterFrame”, collectablebeer)

------------------invisible object that becomes the camera focus when squaddie to player distance is greater than x

local newfocus = display.newRect (arthur.x, arthur.y, 20, 30)

newfocus.strokeWidth = 3

newfocus:setFillColor( 1,1,0 )

newfocus:setStrokeColor( 1, 0, 0 )

map.layer[2]:insert(newfocus)

newfocus.alpha = 0

----------------------------------------------------------------left running button

local leftbutton = display.newRect( screenW/2, display.contentHeight-40, screenW/4, 30 )

leftbutton:setFillColor( 0, 1, 1 )

leftbutton.id = “leftbutton”

gui.front:insert(leftbutton)

--------------------------------------------------------------running mechanism (scrub buttons)

local function onButtonReleaseLeft ()

if touchright == “yes” and canJump > 0 then

audio.play ( runsound )

touchright = “no”

if vx <50 then

arthur:applyLinearImpulse( 1, 0, arthur.x, arthur.y )

end

elseif touchright == “no” then

return true

end

end

-------------------------------------------------------------------jumping functions

local function onJumpButtonRelease ( event )

if event.phase == “began” and arthur.y >105 then

print( “jumped” )

audio.play ( jumped  )

arthur:applyLinearImpulse( 0, -2, arthur.x, arthur.y )

canJump = 0

return true

end

end

-----------------------------------------------------------------squaddie run function

local function squaddierun ()

random = math.random(5)

if random > 1 and sx <80 then

squaddie:applyLinearImpulse( 1.05, 0, squaddie.x, squaddie.y )

end

end

–replaces game objects on leaving game scene ready for replay on return – INCOMPLETE - unsure about this section

local function cleanup ()

squaddie:setSequence(“running”)

squaddie:play()

squaddie.x = -10

squaddie.y = 105

–arthur:setLinearVelocity( 0, 0 )

arthur.x = 140

arthur.y = 106

arthur.isSensor = false

arthur:setSequence(“standing”)

arthur:play()

gameisplaying = 1

gameover = 0

physics.addBody( arthur, “dynamic”, { density=0.9, friction=0.5, bounce=0} )

physics.start()

end

-----------------------------------------------------------when squaddie catches player

local function arthurHit (event)

–arthur:setLinearVelocity( 0, 0 )

arthur:setSequence(“beenhit”)

gameover = 1

vx, vy = 0,0

arthur:play()

arthur:applyLinearImpulse( 2, -2.5, arthur.x, arthur.y )

arthur.isSensor = true

audio.play ( scream  )

timer.performWithDelay( 1000, cleanup )

end

------------------------------------------------sensor trailing player to play alert sound

local arthurrear = display.newRect (arthur.x-140, arthur.y-20, 1, 1)

arthurrear:setFillColor( 1,1,0 )

arthurrear:setStrokeColor( 1, 0, 0 )

map.layer[1]:insert(arthurrear)

arthurrear.alpha = 0

------------------------------------------------detect collision with sensor

local sounded = 0

local function hasCollided( arthurrear, squaddie )

   if ( arthurrear == nil ) then 

      return false

   end

   if ( squaddie == nil ) then  

      return false

   end

   local left = arthurrear.contentBounds.xMin <= squaddie.contentBounds.xMin and arthurrear.contentBounds.xMax >= squaddie.contentBounds.xMin

   local right = arthurrear.contentBounds.xMin >= squaddie.contentBounds.xMin and arthurrear.contentBounds.xMin <= squaddie.contentBounds.xMax

   local up = arthurrear.contentBounds.yMin <= squaddie.contentBounds.yMin and arthurrear.contentBounds.yMax >= squaddie.contentBounds.yMin

   local down = arthurrear.contentBounds.yMin >= squaddie.contentBounds.yMin and arthurrear.contentBounds.yMin <= squaddie.contentBounds.yMax

   return (left or right) and (up or down)

end

local function testCollisions()

         if hasCollided (arthurrear, squaddie) and sounded == 0 then

             audio.play ( watchout )

             sounded = 1

             return true

         end

end

--------------------------------------------makes collectables pass through squaddie

function squaddieCollision( event )

if ( event.phase == “began” ) then

   if (event.other.myName == “collectablebeer” and event.other.isVisible==true) then

    collectablebeer.isSensor = true

   end

end

end

squaddie:addEventListener(“collision”, squaddieCollision)

------------------------------------------if collectable passes off screen, reset to right

local function resetcollectable (self)

self.collected = 0

self.x = (arthur.x - 220)

self.xScale = 1

self.yScale = 1

self.alpha =1

self.isSensor = false

self.speed = math.random (1,3)

self.y = math.random(32, 96)

self.initY = self.y

self.amp = math.random(5,32)

self.angle = math.random (1, 360)

self.x = self.x - self.speed

self.angle = self.angle + 0.1

self.y = self.amp * math.sin(self.angle) + self.initY

end

--------------------------------------------ending the game if the squaddie catches player

local function failed (event)

composer.gotoScene( “gameover”, “slideDown”, 200 )

end

-------------------------------------------effects of collisions with player

function onCollision( event )

if ( event.phase == “began” ) then

   if (event.other.myName == “squaddie” and event.other.isVisible==true) then

        squaddie:applyLinearImpulse( 6, 0, squaddie.x, squaddie.y )

        squaddie:setSequence(“punch”)

squaddie:play()

Runtime:removeEventListener( “enterFrame”, onEveryFrame )

timer.performWithDelay( 290, arthurHit )

timer.performWithDelay( 1000, failed)

        

    return true

   elseif (event.other.myName == “pubdoor” and event.other.isVisible==true) then

        audio.play ( beep )

        arthur.alpha = 0

        Runtime:removeEventListener( “enterFrame”, onEveryFrame )

        composer.gotoScene( “success”, “zoomInOutFade”, 200 )

  composer.removeScene(“level1”)

  return true

  elseif (event.other.myName == map.ground) then

  canJump = 1

  return true

  end 

end

end

arthur:addEventListener(“collision”, onCollision)

--------------------------check distance between squaddie and player, adjust camera

local function distanceCheck ( )

local distancex = arthur.x - squaddie.x

local backx = arthurrear.x - squaddie.x

if backx >40 then

sounded = 0

end

newfocus.x = arthur.x

newfocus.y = 106

if distancex > 200 then

transition.scaleTo( map, { xScale=2.3, yScale=2.3, time=1500 } )

map.setCameraFocus(newfocus)

map.updateView()

else if distancex <= 200 then

transition.scaleTo( map, { xScale=3.1, yScale=3.1, time=1500 } )

map.setCameraFocus(newfocus)

map.updateView()

end

end

end

--------------------------------------------------------------------gameloop?

function onEveryFrame( e )

if gameisplaying == 1 then

squaddierun ()

vx, vy = arthur:getLinearVelocity()

sx, sy = squaddie:getLinearVelocity( )

motioncheck (vx)

distanceCheck ()

end

distanceCheck ()

arthurrear.x = arthur.x -140

beerscoretext.text = myData.beerscore

end

Runtime:addEventListener( “enterFrame”, onEveryFrame )

end


function scene:show( event )


local sceneGroup = self.view

local phase = event.phase

if phase == “will” then

elseif phase == “did” then

physics.start()

end

end


function scene:hide( event )


local sceneGroup = self.view

local phase = event.phase

if event.phase == “will” then

elseif phase == “did” then

physics.stop() – not sure of I should leave this running?

end

end

function scene:destroy( event )

local sceneGroup = self.view

end

scene:addEventListener( “create”, scene )

scene:addEventListener( “show”, scene )

scene:addEventListener( “hide”, scene )

scene:addEventListener( “destroy”, scene )

return scene


------------------------- GAME OVER LUA FILE FROM HERE ------------------------------


local composer = require( “composer” )

local scene = composer.newScene()

local myData = require( “mydata” )

local screenW, screenH, halfW = display.contentWidth, display.contentHeight, display.contentWidth*0.5

function scene:create( event )

local sceneGroup = self.view

endgui = display.newGroup()

local background = display.newImageRect( “background.png”, display.contentWidth, display.contentHeight )

background.anchorX = 0

background.anchorY = 0

background.x, background.y = 0, 10

local sheet15 = graphics.newImageSheet( “rerun.png”, { width=200, height=40, numFrames=2 } )

local rerunButton =

{

   { name=“blink2”, start=1, count=2, time=1500 }

}

local rerun = display.newSprite( sheet15, rerunButton)

rerun.x = display.contentWidth * 0.68

rerun.y = display.contentHeight - 60

rerun:setSequence(“blink2”)

rerun:play()

local function onRerunBtnRelease()

rerun:removeEventListener( “touch”, onRerunBtnRelease )

composer.gotoScene( “game”, “fade”, 500 )

return true

end

rerun:addEventListener( “touch”, onRerunBtnRelease )

------------------------------------------------------------------display number of collected items

local myCircle = display.newCircle( ((screenW/10) * 3.25)+5,  25, 11 )

myCircle:setFillColor( 0 )

endgui:insert(myCircle)

local beerscoretext = display.newText( “” … myData.beerscore, ((screenW/10) * 3.25)+5,  25, native.systemFont, 14 )

beerscoretext:setFillColor( 1, 1, 1 )

beerscoretext.align = “center”

endgui:insert(beerscoretext)

print (beerscoretext)

sceneGroup:insert( background )

sceneGroup:insert( rerun )

sceneGroup:insert( endgui )

end

function scene:show( event )

local sceneGroup = self.view

local phase = event.phase

if phase == “will” then

elseif phase == “did” then

end

end

function scene:hide( event )

local sceneGroup = self.view

local phase = event.phase

if event.phase == “will” then

elseif phase == “did” then

end

end

function scene:destroy( event )

local sceneGroup = self.view

end

scene:addEventListener( “create”, scene )

scene:addEventListener( “show”, scene )

scene:addEventListener( “hide”, scene )

scene:addEventListener( “destroy”, scene )

return scene

[/lua]

One thing you might consider is using a blank.lua file. In that file, copy the composer template. In your onRerunBtnRelease function, point to the blank scene, rather than the game scene. In the blank scene, use a timer to remove gameover scene and load the game scene. It would look like this:

local composer = require( "composer" ) local scene = composer.newScene() local function reloadLvl() composer.removeScene("gameOver") composer.gotoScene("game") end --------------------------------------------------------------------------------- function scene:create( event ) timer.performWithDelay( 1000, reloadLvl) -- Called when the scene's view does not exist. -- -- INSERT code here to initialize the scene -- e.g. add display objects to 'sceneGroup', add touch listeners, etc. end function scene:show( event ) local sceneGroup = self.view local phase = event.phase if phase == "will" then -- Called when the scene is still off screen and is about to move on screen elseif phase == "did" then -- Called when the scene is now on screen -- -- INSERT code here to make the scene come alive -- e.g. start timers, begin animation, play audio, etc. end end function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if event.phase == "will" then -- Called when the scene is on screen and is about to move off screen -- -- INSERT code here to pause the scene -- e.g. stop timers, stop animation, unload sounds, etc.) elseif phase == "did" then -- Called when the scene is now off screen end end function scene:destroy( event ) local sceneGroup = self.view -- Called prior to the removal of scene's "view" (sceneGroup) -- -- INSERT code here to cleanup the scene -- e.g. remove display objects, remove touch listeners, save state, etc. end --------------------------------------------------------------------------------- -- Listener setup scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) --------------------------------------------------------------------------------- return scene

Thanks very much James - this really helps - no errors now. The control buttons don’t work but I’ll check my game code.

I suppose it depends on the size of the game and assets used but would you usually remove everything when leaving the game, or reset everything ready for your return?

I think the penny might just have dropped - does moving to a blank file and removing the gameover scene work because the event listeners or something in the game over scene are conflicting with the game scene?

Many thanks.

I’ve been working on this for a while longer and I’m back where I started.

I can get the game - gameover sequence to run twice then I get a black screen. The second time around the character jumps too high (yet there is no change to linearimpulse values).

I found this http://forums.coronalabs.com/topic/34421-storyboard-not-reinitializing-physics-when-purgeonscenechange-is-used/ and decided to try removing the game scene by listing assets to remove in game lua’s scene:destroy, and adding another blank file with composer.removeScene(“game”) in the hope to achieve this:

game – blank (remove game) – game over – blank (remove gameover) – game…

but on leaving the first game sequence I get the same errors as earlier:

Attempt to index upvalue ‘runsound’ (a userdata value)

… and so on through the list of assets I’ve added in the game scene:destroy section.

As an example, I’m trying to remove runsound like this:

[lua]

runsound:removeSelf()

runsound = nil

[/lua]

Is this correct for a short sound effect?

Is there a sure fire way to clear out everything at the point of reaching the gameover scene and starting the game fresh?

Hi, sorry for continuing with this, I realise my last post there might not have been very helpful/clear but I’m up against a deadline and I just hope to resolve this and learn a bit more in the process.

I’ve read various things about Composer clearing up elements in the scene group, but then other posts say that elements need to be removed. I’ve tried the following in destroy scene (all display objects are in a scene group):

transition.cancel() 

physics.removeBody( object )

physics.stop()

Runtime:removeEventListener( “enterFrame”, functionname )

object:removeEventListener( “touch”, function )

package.loaded[physics] = nil

physics = nil

object:removeSelf()

    and 

display.remove(object)

object = nil

I think all objects have been listed with regard to clearing them up but when I return to the game from the game over screen it’s as if the game scene was left as is right after the end of the game - physics objects are still moving, sounds still occur when triggered… although some display elements are removed and some funcitons/processes aren’t running.

Further to any comments on the above I’ve two specific questions if I may:

  1. ‘table: 0x7ff2a4847940’ is printed in the terminal right at the point when the game ends/scene transition occurs - could this be relevant or indicative of anything?

  2. Is it possible almost to ‘remove the package’ to clear the game lua file from memory? (Does it work that way?)

Many thanks for any help.

Newbie,

Just scrolled thru your code quickly, and noticed you may not have every ‘display object’ inserted into the sceneGroup. I see some of the stuff is inserted into gui-group which in turn is inserted into the sceneGroup, which is okay.  But there are (best I could see quickly scrolling thru your code) several display objects that are not inserted into sceneGroup. 

For instance, you have map.layer:insert(some display rect)…   but where is map (assuming map is a display group or such, or the map module returns or has access to some display group of the map and map layer) inserted into sceneGroup?

I don’t have that much experience with composer, but I do understand that all display objects need to get inserted into the sceneGroup if you want composer to handle hiding or removing them when you exit the scene.  Obviously the other scene you call, covers first scene temporarily but that doesn’t mean composer handled removing/clearing or hiding first scene … or at least not the display objects not inserted into sceneGroup of your first scene.  

I see you have nothing in the sceneShow function which seems unusual to me, but I do not think it is required that there be code there, just unusual, depending on what you want the code to do.

If I could suggest, Corona Geek I think has a discussion last week about composer that you might watch and get a better feel for it.

Good luck

Thanks very much I’ll check those objects and add them to a scene group and ill check out CoronaGeek.

I probably overlooked adding to sceneShow but I’ll make use of that next time.

I keep getting errors with:

‘Attempt to call method ‘getLinearVelocity’ (a nil value)’ from line 428

and

Attempt to call method ‘applyLinearImpulse’ (a nil value) from line 266

for the first I’ve added:

Runtime:removeEventListener( “enterFrame”, onEveryFrame ) in destroy scene and I’ve removed the object that it apples to. 

I’ve changed both functions to include ‘if then else’ statements like in the following but the errors still occur…

[lua]

local function onEveryFrame( e )

if gameisplaying == 1 then

squaddierun ()

if arthur then vx, vy = arthur:getLinearVelocity() else vz, vy = 0,0 end

if squaddie then sx, sy = squaddie:getLinearVelocity( ) else sx, sy = 0,0 end 

motioncheck (vx)

distanceCheck ()

distanceGauge ()

end

distanceCheck ()

arthurrear.x = arthur.x -140

beerscoretext.text = myData.beerscore

end

Runtime:addEventListener( “enterFrame”, onEveryFrame )

[/lua]

Any idea if I need to do anything particular with get/applyLinearVelocity() when changing scenes?

I am not that familiar with the physics engine. I have used it a little, but never the linearVelocity or linearImpulse. Sorry.

Once you check out the corona geek on composer you may have a better feel of what needs or does not need to be done in the sceneShow function.  It really depends on what you wan the scene to being doing when it shows compared to when it is created.  Some of the initial tutorials should explain that fairly well.

Good luck

Thanks very much, I appreciate your advice.

Code would be helpful. You don’t need to post everything, just show us your main game scene and your game over scene. 

Hi James thanks for replying.

Here’s my code - I’ve taken out a few things where I could but this is the gist of it. The game over code is indicated towards the end.

I realise this is long - I’m still learning and I guess my next lesson will be modules.

Since posting my original question I’m a small step closer to repositioning everything just before leaving the game scene - not removing anything - and then having it ready to begin when the player returns. The issue right now is when I try to move the character on returning to the game I get ‘Attempt to call method ‘applyLinearImpulse’ (a nil value)’.

I think the main problem is that the game file is so long and everything has become so interconnected that if I reposition anything I get errors. I know maybe I ought to have put some things in different scene functions… could that be an issue? I’d just like to be able to ‘restart’ the game either by returning to a reinitialised state, or by removing all elements and rebuilding. 

To give you a picture of the game - the player character is Arthur - he’s chased by a squaddie. Arthur either gets caught and it’s game over, or he makes it to the end and succeeds. On the way he collects objects - one shown here is beer. The score is displayed on the end screen (via a myData.lua file to pass the variable).

Many thanks for any help, this is driving me around the bend.

[lua]


– game.lua


display.setStatusBar(display.HiddenStatusBar)

local composer = require( “composer” )

local scene = composer.newScene()

local myData = require( “mydata” )

local physics = require( “physics” )

system.activate( “multitouch” )

physics.start()

physics.pause()

local textureFilter = “nearest”

local screenW, screenH, halfW = display.contentWidth, display.contentHeight, display.contentWidth*0.5

local arthur

local map

local touchright = “yes”

local touchleft = “yes”

local score

local speed

local leftbutton

local rightbutton

local jumpbutton

local framerate = 900

local vx = 0

local vy = 0

local sx = 0

local sy = 0

local canJump = 0

local runsound = audio.loadSound ( “audio/runsound.wav” )

local gameisplaying = 0

local gameover = 0

local dusk = require(“Dusk.Dusk”)

map = dusk.buildMap(“levelgraphic2.json”)

map:scale (1, 1)

map.setTrackingLevel(0.9)

map.setCameraBounds ({ xMin = display.contentCenterX, yMin = display.contentCenterY, xMax = map.data.width - display.contentCenterX, yMax = map.data.height - display.contentCenterY })

map.layer[1].setCameraOffset(14, 24)

map.layer[2].setCameraOffset(14, 24)


function scene:create( event )


local sceneGroup = self.view

----------------------------------------------------------scene management

gui = display.newGroup()

gui.front = display.newGroup()

gui.back = display.newGroup()

gui:insert(gui.back) --map is in here (characters are in map)

gui:insert(gui.front) --buttons

gui.back:insert(map)

sceneGroup:insert(gui)

----------------------------------------------------------Target for level completion

local pubdoor = display.newImageRect( “pubdoor.png”, 40, 55 )

pubdoor.x, pubdoor.y =  map.data.width - 128, 106

physics.addBody( pubdoor, “static” )

pubdoor.id = “pubdoor”

pubdoor.title = “pubdoor”

pubdoor.myName = “pubdoor”

map.layer[1]:insert(pubdoor)

---------------------------------------------------------Player

local sheet1 = graphics.newImageSheet( “arthur.png”, { width=25, height=37, numFrames=14 } )

local arthurData =

{

   { name=“standing”, frames= { 13 } },

   { name=“running”, start=1, count=12, time=framerate },

   { name=“beenhit”, frames= { 14 } }

}

local arthur = display.newSprite( sheet1, arthurData )

arthur.x = 140

arthur.y = 106

arthur.id = “arthur”

arthur.title = “arthur”

arthur.myName = “arthur”

arthur.rotation = 0

arthur.anchorY = 1

arthur.anchorX = 0.5

arthur:setSequence(“standing”)

arthur:play()

physics.addBody( arthur, “dynamic”, { density=0.9, friction=0.5, bounce=0} )

arthur.isFixedRotation = true

map.layer[1]:insert(arthur)

-------------------------------check for movement and set correct animation for player

local function motioncheck (vx)

local current_sequence = arthur.sequence

if vx > 1.5 then

if current_sequence == “running” then

return true

else 

arthur:setSequence( “running” )

arthur:play()

end

end

if vx <= 1.5 then

if current_sequence == “standing” then

return true

else

arthur:setSequence(“standing”)

arthur:play()

end

end

end

---------------------------------------------------------------Create Squaddie 

local sheet2 = graphics.newImageSheet( “squaddie.png”, { width=25, height=37, numFrames=16 } )

local squaddieData =

{

   { name=“running”, start=1, count=12, time=framerate },

   { name=“punch”, start=14, count=3, time=500, loopCount =1 }

}

local squaddie = display.newSprite( sheet2, squaddieData)

squaddie.x = -10

squaddie.y = 105

squaddie.id = “squaddie”

squaddie.title = “squaddie”

squaddie.myName = “squaddie”

squaddie:setSequence(“running”)

squaddie:play()

physics.addBody( squaddie, “dynamic”, { density=2, friction=1, bounce=0.0  } )

squaddie.isFixedRotation = true

map.layer[1]:insert(squaddie)

----------------------------------------------------Graphics at the top of the screen

------BEER---------

local beerGlimmer = display.newImageRect( “glimmer.png”, 35, 35 )

beerGlimmer.anchorX = 0.5

beerGlimmer.anchorY = 0.5

beerGlimmer.xScale = 2

beerGlimmer.yScale = 2

beerGlimmer.x, beerGlimmer.y =  (screenW/10) * 7,  20

gui.front:insert(beerGlimmer)

local sheet3 = graphics.newImageSheet( “beerweb.png”, { width=12, height=12, numFrames=6, sheetContentWidth=72, sheetContentHeight=12} )

local beerData =

{

  { name=“beerpause”, frames = {1}, time=3000, loopCount =1},

  { name=“beershining”, frames = {2,3,4,5,6}, time=300, loopCount =1 }

}

local beer = display.newSprite( sheet3, beerData )

beer.x = (screenW/10) * 7

beer.y = 20

beer:setSequence(“beerpause”)

beer:play()

gui.front:insert(beer)

local function beerListener( event ) 

local beer_sequence = beer.sequence

if ( event.phase == “ended” ) and beer_sequence == “beerpause” then

local beerData = target

  beer:setSequence( “beershining” )

  beer:play()

elseif ( event.phase == “ended” ) and beer_sequence == “beershining” then

local beerData = target

  beer:setSequence( “beerpause” )

  beer:play()

  end

end

local function spinBeerGlimmer (event)

transition.to( beerGlimmer, { rotation = beerGlimmer.rotation-360, time=4000, onComplete=spinBeerGlimmer } )

end

-------------------------------------------display number of collected items

local beerscoretext = display.newText( “” , ((screenW/10) * 7)+3, 44, native.systemFont, 14 )

beerscoretext:setFillColor( 1, 1, 1 )

beerscoretext.align = “center”

gui.front:insert(beerscoretext)

------------------------------------------Collectables that float in

---- collectable beer-------

local collectablebeer = display.newSprite( sheet3, beerData )

collectablebeer:setSequence(“beershining”)

collectablebeer.collected = 0

collectablebeer:play()

collectablebeer.x = 350

collectablebeer.y = math.random (32, 96)

map.layer [1]:insert(collectablebeer)

physics.addBody( collectablebeer, “static”, { density=0.1, friction=1, bounce=0.0, radius = 5  } )

collectablebeer.isFixedRotation = true

collectablebeer.speed = 0

collectablebeer.initY = collectablebeer.y

collectablebeer.amp = math.random(5,32)

collectablebeer.angle = math.random (1, 360)

collectablebeer.myName = “collectablebeer”

local function collectablebeerListener( event ) 

local collectablebeer_sequence = collectablebeer.sequence

if ( event.phase == “ended” ) and collectablebeer_sequence == “beerpause” then

local collectablebeerData = target

  collectablebeer:setSequence( “beershining” )

  collectablebeer:play()

elseif ( event.phase == “ended” ) and collectablebeer_sequence == “beershining” then

local collectablebeerData = target

  collectablebeer:setSequence( “beerpause” )

  collectablebeer:play()

  end

end

collectablebeer:addEventListener( “sprite”, collectablebeerListener )

function scrollcollectbeer (self, event)

if self.x < (arthur.x-200) then

self.x = (arthur.x + 200)

else

if collectablebeer.collected == 0 then

self.x = self.x - self.speed

self.angle = self.angle + 0.1

self.y = self.amp * math.sin(self.angle) + self.initY

end

end

end

collectablebeer.enterFrame = scrollcollectbeer

Runtime:addEventListener(“enterFrame”, collectablebeer)

------------------invisible object that becomes the camera focus when squaddie to player distance is greater than x

local newfocus = display.newRect (arthur.x, arthur.y, 20, 30)

newfocus.strokeWidth = 3

newfocus:setFillColor( 1,1,0 )

newfocus:setStrokeColor( 1, 0, 0 )

map.layer[2]:insert(newfocus)

newfocus.alpha = 0

----------------------------------------------------------------left running button

local leftbutton = display.newRect( screenW/2, display.contentHeight-40, screenW/4, 30 )

leftbutton:setFillColor( 0, 1, 1 )

leftbutton.id = “leftbutton”

gui.front:insert(leftbutton)

--------------------------------------------------------------running mechanism (scrub buttons)

local function onButtonReleaseLeft ()

if touchright == “yes” and canJump > 0 then

audio.play ( runsound )

touchright = “no”

if vx <50 then

arthur:applyLinearImpulse( 1, 0, arthur.x, arthur.y )

end

elseif touchright == “no” then

return true

end

end

-------------------------------------------------------------------jumping functions

local function onJumpButtonRelease ( event )

if event.phase == “began” and arthur.y >105 then

print( “jumped” )

audio.play ( jumped  )

arthur:applyLinearImpulse( 0, -2, arthur.x, arthur.y )

canJump = 0

return true

end

end

-----------------------------------------------------------------squaddie run function

local function squaddierun ()

random = math.random(5)

if random > 1 and sx <80 then

squaddie:applyLinearImpulse( 1.05, 0, squaddie.x, squaddie.y )

end

end

–replaces game objects on leaving game scene ready for replay on return – INCOMPLETE - unsure about this section

local function cleanup ()

squaddie:setSequence(“running”)

squaddie:play()

squaddie.x = -10

squaddie.y = 105

–arthur:setLinearVelocity( 0, 0 )

arthur.x = 140

arthur.y = 106

arthur.isSensor = false

arthur:setSequence(“standing”)

arthur:play()

gameisplaying = 1

gameover = 0

physics.addBody( arthur, “dynamic”, { density=0.9, friction=0.5, bounce=0} )

physics.start()

end

-----------------------------------------------------------when squaddie catches player

local function arthurHit (event)

–arthur:setLinearVelocity( 0, 0 )

arthur:setSequence(“beenhit”)

gameover = 1

vx, vy = 0,0

arthur:play()

arthur:applyLinearImpulse( 2, -2.5, arthur.x, arthur.y )

arthur.isSensor = true

audio.play ( scream  )

timer.performWithDelay( 1000, cleanup )

end

------------------------------------------------sensor trailing player to play alert sound

local arthurrear = display.newRect (arthur.x-140, arthur.y-20, 1, 1)

arthurrear:setFillColor( 1,1,0 )

arthurrear:setStrokeColor( 1, 0, 0 )

map.layer[1]:insert(arthurrear)

arthurrear.alpha = 0

------------------------------------------------detect collision with sensor

local sounded = 0

local function hasCollided( arthurrear, squaddie )

   if ( arthurrear == nil ) then 

      return false

   end

   if ( squaddie == nil ) then  

      return false

   end

   local left = arthurrear.contentBounds.xMin <= squaddie.contentBounds.xMin and arthurrear.contentBounds.xMax >= squaddie.contentBounds.xMin

   local right = arthurrear.contentBounds.xMin >= squaddie.contentBounds.xMin and arthurrear.contentBounds.xMin <= squaddie.contentBounds.xMax

   local up = arthurrear.contentBounds.yMin <= squaddie.contentBounds.yMin and arthurrear.contentBounds.yMax >= squaddie.contentBounds.yMin

   local down = arthurrear.contentBounds.yMin >= squaddie.contentBounds.yMin and arthurrear.contentBounds.yMin <= squaddie.contentBounds.yMax

   return (left or right) and (up or down)

end

local function testCollisions()

         if hasCollided (arthurrear, squaddie) and sounded == 0 then

             audio.play ( watchout )

             sounded = 1

             return true

         end

end

--------------------------------------------makes collectables pass through squaddie

function squaddieCollision( event )

if ( event.phase == “began” ) then

   if (event.other.myName == “collectablebeer” and event.other.isVisible==true) then

    collectablebeer.isSensor = true

   end

end

end

squaddie:addEventListener(“collision”, squaddieCollision)

------------------------------------------if collectable passes off screen, reset to right

local function resetcollectable (self)

self.collected = 0

self.x = (arthur.x - 220)

self.xScale = 1

self.yScale = 1

self.alpha =1

self.isSensor = false

self.speed = math.random (1,3)

self.y = math.random(32, 96)

self.initY = self.y

self.amp = math.random(5,32)

self.angle = math.random (1, 360)

self.x = self.x - self.speed

self.angle = self.angle + 0.1

self.y = self.amp * math.sin(self.angle) + self.initY

end

--------------------------------------------ending the game if the squaddie catches player

local function failed (event)

composer.gotoScene( “gameover”, “slideDown”, 200 )

end

-------------------------------------------effects of collisions with player

function onCollision( event )

if ( event.phase == “began” ) then

   if (event.other.myName == “squaddie” and event.other.isVisible==true) then

        squaddie:applyLinearImpulse( 6, 0, squaddie.x, squaddie.y )

        squaddie:setSequence(“punch”)

squaddie:play()

Runtime:removeEventListener( “enterFrame”, onEveryFrame )

timer.performWithDelay( 290, arthurHit )

timer.performWithDelay( 1000, failed)

        

    return true

   elseif (event.other.myName == “pubdoor” and event.other.isVisible==true) then

        audio.play ( beep )

        arthur.alpha = 0

        Runtime:removeEventListener( “enterFrame”, onEveryFrame )

        composer.gotoScene( “success”, “zoomInOutFade”, 200 )

  composer.removeScene(“level1”)

  return true

  elseif (event.other.myName == map.ground) then

  canJump = 1

  return true

  end 

end

end

arthur:addEventListener(“collision”, onCollision)

--------------------------check distance between squaddie and player, adjust camera

local function distanceCheck ( )

local distancex = arthur.x - squaddie.x

local backx = arthurrear.x - squaddie.x

if backx >40 then

sounded = 0

end

newfocus.x = arthur.x

newfocus.y = 106

if distancex > 200 then

transition.scaleTo( map, { xScale=2.3, yScale=2.3, time=1500 } )

map.setCameraFocus(newfocus)

map.updateView()

else if distancex <= 200 then

transition.scaleTo( map, { xScale=3.1, yScale=3.1, time=1500 } )

map.setCameraFocus(newfocus)

map.updateView()

end

end

end

--------------------------------------------------------------------gameloop?

function onEveryFrame( e )

if gameisplaying == 1 then

squaddierun ()

vx, vy = arthur:getLinearVelocity()

sx, sy = squaddie:getLinearVelocity( )

motioncheck (vx)

distanceCheck ()

end

distanceCheck ()

arthurrear.x = arthur.x -140

beerscoretext.text = myData.beerscore

end

Runtime:addEventListener( “enterFrame”, onEveryFrame )

end


function scene:show( event )


local sceneGroup = self.view

local phase = event.phase

if phase == “will” then

elseif phase == “did” then

physics.start()

end

end


function scene:hide( event )


local sceneGroup = self.view

local phase = event.phase

if event.phase == “will” then

elseif phase == “did” then

physics.stop() – not sure of I should leave this running?

end

end

function scene:destroy( event )

local sceneGroup = self.view

end

scene:addEventListener( “create”, scene )

scene:addEventListener( “show”, scene )

scene:addEventListener( “hide”, scene )

scene:addEventListener( “destroy”, scene )

return scene


------------------------- GAME OVER LUA FILE FROM HERE ------------------------------


local composer = require( “composer” )

local scene = composer.newScene()

local myData = require( “mydata” )

local screenW, screenH, halfW = display.contentWidth, display.contentHeight, display.contentWidth*0.5

function scene:create( event )

local sceneGroup = self.view

endgui = display.newGroup()

local background = display.newImageRect( “background.png”, display.contentWidth, display.contentHeight )

background.anchorX = 0

background.anchorY = 0

background.x, background.y = 0, 10

local sheet15 = graphics.newImageSheet( “rerun.png”, { width=200, height=40, numFrames=2 } )

local rerunButton =

{

   { name=“blink2”, start=1, count=2, time=1500 }

}

local rerun = display.newSprite( sheet15, rerunButton)

rerun.x = display.contentWidth * 0.68

rerun.y = display.contentHeight - 60

rerun:setSequence(“blink2”)

rerun:play()

local function onRerunBtnRelease()

rerun:removeEventListener( “touch”, onRerunBtnRelease )

composer.gotoScene( “game”, “fade”, 500 )

return true

end

rerun:addEventListener( “touch”, onRerunBtnRelease )

------------------------------------------------------------------display number of collected items

local myCircle = display.newCircle( ((screenW/10) * 3.25)+5,  25, 11 )

myCircle:setFillColor( 0 )

endgui:insert(myCircle)

local beerscoretext = display.newText( “” … myData.beerscore, ((screenW/10) * 3.25)+5,  25, native.systemFont, 14 )

beerscoretext:setFillColor( 1, 1, 1 )

beerscoretext.align = “center”

endgui:insert(beerscoretext)

print (beerscoretext)

sceneGroup:insert( background )

sceneGroup:insert( rerun )

sceneGroup:insert( endgui )

end

function scene:show( event )

local sceneGroup = self.view

local phase = event.phase

if phase == “will” then

elseif phase == “did” then

end

end

function scene:hide( event )

local sceneGroup = self.view

local phase = event.phase

if event.phase == “will” then

elseif phase == “did” then

end

end

function scene:destroy( event )

local sceneGroup = self.view

end

scene:addEventListener( “create”, scene )

scene:addEventListener( “show”, scene )

scene:addEventListener( “hide”, scene )

scene:addEventListener( “destroy”, scene )

return scene

[/lua]

One thing you might consider is using a blank.lua file. In that file, copy the composer template. In your onRerunBtnRelease function, point to the blank scene, rather than the game scene. In the blank scene, use a timer to remove gameover scene and load the game scene. It would look like this:

local composer = require( "composer" ) local scene = composer.newScene() local function reloadLvl() composer.removeScene("gameOver") composer.gotoScene("game") end --------------------------------------------------------------------------------- function scene:create( event ) timer.performWithDelay( 1000, reloadLvl) -- Called when the scene's view does not exist. -- -- INSERT code here to initialize the scene -- e.g. add display objects to 'sceneGroup', add touch listeners, etc. end function scene:show( event ) local sceneGroup = self.view local phase = event.phase if phase == "will" then -- Called when the scene is still off screen and is about to move on screen elseif phase == "did" then -- Called when the scene is now on screen -- -- INSERT code here to make the scene come alive -- e.g. start timers, begin animation, play audio, etc. end end function scene:hide( event ) local sceneGroup = self.view local phase = event.phase if event.phase == "will" then -- Called when the scene is on screen and is about to move off screen -- -- INSERT code here to pause the scene -- e.g. stop timers, stop animation, unload sounds, etc.) elseif phase == "did" then -- Called when the scene is now off screen end end function scene:destroy( event ) local sceneGroup = self.view -- Called prior to the removal of scene's "view" (sceneGroup) -- -- INSERT code here to cleanup the scene -- e.g. remove display objects, remove touch listeners, save state, etc. end --------------------------------------------------------------------------------- -- Listener setup scene:addEventListener( "create", scene ) scene:addEventListener( "show", scene ) scene:addEventListener( "hide", scene ) scene:addEventListener( "destroy", scene ) --------------------------------------------------------------------------------- return scene

Thanks very much James - this really helps - no errors now. The control buttons don’t work but I’ll check my game code.

I suppose it depends on the size of the game and assets used but would you usually remove everything when leaving the game, or reset everything ready for your return?

I think the penny might just have dropped - does moving to a blank file and removing the gameover scene work because the event listeners or something in the game over scene are conflicting with the game scene?

Many thanks.

I’ve been working on this for a while longer and I’m back where I started.

I can get the game - gameover sequence to run twice then I get a black screen. The second time around the character jumps too high (yet there is no change to linearimpulse values).

I found this http://forums.coronalabs.com/topic/34421-storyboard-not-reinitializing-physics-when-purgeonscenechange-is-used/ and decided to try removing the game scene by listing assets to remove in game lua’s scene:destroy, and adding another blank file with composer.removeScene(“game”) in the hope to achieve this:

game – blank (remove game) – game over – blank (remove gameover) – game…

but on leaving the first game sequence I get the same errors as earlier:

Attempt to index upvalue ‘runsound’ (a userdata value)

… and so on through the list of assets I’ve added in the game scene:destroy section.

As an example, I’m trying to remove runsound like this:

[lua]

runsound:removeSelf()

runsound = nil

[/lua]

Is this correct for a short sound effect?

Is there a sure fire way to clear out everything at the point of reaching the gameover scene and starting the game fresh?

Hi, sorry for continuing with this, I realise my last post there might not have been very helpful/clear but I’m up against a deadline and I just hope to resolve this and learn a bit more in the process.

I’ve read various things about Composer clearing up elements in the scene group, but then other posts say that elements need to be removed. I’ve tried the following in destroy scene (all display objects are in a scene group):

transition.cancel() 

physics.removeBody( object )

physics.stop()

Runtime:removeEventListener( “enterFrame”, functionname )

object:removeEventListener( “touch”, function )

package.loaded[physics] = nil

physics = nil

object:removeSelf()

    and 

display.remove(object)

object = nil

I think all objects have been listed with regard to clearing them up but when I return to the game from the game over screen it’s as if the game scene was left as is right after the end of the game - physics objects are still moving, sounds still occur when triggered… although some display elements are removed and some funcitons/processes aren’t running.

Further to any comments on the above I’ve two specific questions if I may:

  1. ‘table: 0x7ff2a4847940’ is printed in the terminal right at the point when the game ends/scene transition occurs - could this be relevant or indicative of anything?

  2. Is it possible almost to ‘remove the package’ to clear the game lua file from memory? (Does it work that way?)

Many thanks for any help.

Newbie,

Just scrolled thru your code quickly, and noticed you may not have every ‘display object’ inserted into the sceneGroup. I see some of the stuff is inserted into gui-group which in turn is inserted into the sceneGroup, which is okay.  But there are (best I could see quickly scrolling thru your code) several display objects that are not inserted into sceneGroup. 

For instance, you have map.layer:insert(some display rect)…   but where is map (assuming map is a display group or such, or the map module returns or has access to some display group of the map and map layer) inserted into sceneGroup?

I don’t have that much experience with composer, but I do understand that all display objects need to get inserted into the sceneGroup if you want composer to handle hiding or removing them when you exit the scene.  Obviously the other scene you call, covers first scene temporarily but that doesn’t mean composer handled removing/clearing or hiding first scene … or at least not the display objects not inserted into sceneGroup of your first scene.  

I see you have nothing in the sceneShow function which seems unusual to me, but I do not think it is required that there be code there, just unusual, depending on what you want the code to do.

If I could suggest, Corona Geek I think has a discussion last week about composer that you might watch and get a better feel for it.

Good luck

Thanks very much I’ll check those objects and add them to a scene group and ill check out CoronaGeek.

I probably overlooked adding to sceneShow but I’ll make use of that next time.

I keep getting errors with:

‘Attempt to call method ‘getLinearVelocity’ (a nil value)’ from line 428

and

Attempt to call method ‘applyLinearImpulse’ (a nil value) from line 266

for the first I’ve added:

Runtime:removeEventListener( “enterFrame”, onEveryFrame ) in destroy scene and I’ve removed the object that it apples to. 

I’ve changed both functions to include ‘if then else’ statements like in the following but the errors still occur…

[lua]

local function onEveryFrame( e )

if gameisplaying == 1 then

squaddierun ()

if arthur then vx, vy = arthur:getLinearVelocity() else vz, vy = 0,0 end

if squaddie then sx, sy = squaddie:getLinearVelocity( ) else sx, sy = 0,0 end 

motioncheck (vx)

distanceCheck ()

distanceGauge ()

end

distanceCheck ()

arthurrear.x = arthur.x -140

beerscoretext.text = myData.beerscore

end

Runtime:addEventListener( “enterFrame”, onEveryFrame )

[/lua]

Any idea if I need to do anything particular with get/applyLinearVelocity() when changing scenes?

I am not that familiar with the physics engine. I have used it a little, but never the linearVelocity or linearImpulse. Sorry.

Once you check out the corona geek on composer you may have a better feel of what needs or does not need to be done in the sceneShow function.  It really depends on what you wan the scene to being doing when it shows compared to when it is created.  Some of the initial tutorials should explain that fairly well.

Good luck