How to update all objects in a scene?

Hi.

I’m coming from writing my own game loops from scratch and setting things up the way I like them, so Corona is kind of jarring for me as it does things very differently!

I’ve spent a couple hours Googling, but didn’t make any progress.

My typical game structure would be something like:

  1. create game instance

  2. at regular intervals, call game.update()

  3. in the game.update() call, I would get all the objects in the current scene and call their update functions.

  4. draw everything.

I think this is a very standard game loop with no surprises.

I’ve tried to recreate this in Corona, but failed.

In my current code, I listen for enterFrame events and called the my game update function. What I would then like to do is fetch the current scene and update the appropriate objects. But Corona doesn’t seem setup this way…

How do I get all the objects that are in the current scene? How do I maintain a connection between the scenes and the game?

Sorry, but I’m really struggling to understand how to build my game loop here.

Think of a scene as complete app. It does all the work for what is currently on screen. In other words a Menu scene, a game setting scene or a game over scene doesn’t need to know anything about your game scene (* other than some data!). Your enterFrame listener, timers, physics, and objects are all best contained within the one scene.

Now some events, like back key handling on Android, or low memory events, in app purchases and such can be in main.lua and handle events that come in.

But Composer is really cool because you can call composer.getScene(“current”) from say an In App purchase transaction to get the current scene. If you’ve created functions in that scene that you add to the scene object you can then reference them elsewhere.

Lets say someone where your game.lua scene you define a function:

local coins function scene.handleBuyCoinsPurchase( numCoins )     coins = coins + numCoins end

Now in your in app purchase transaction listener you can do:

local function transactionCallback( event )     local transaction = event.transaction     local tstate = event.transaction.state     if tstate == "purchased" then           local currentScene = composer.getScene( "current" )           currentScene.handleBuyCoinsPurchase( 100 )    end    .... end

If there are data variables that need to be shared between scenes or app wide, there are multiple ways to do it.

  1. Pass paramters. composer.gotoScene() takes an options table that can include a child table that can contain key-value pairs. They are available in scene:create() and scene show:

    composer.gotoScene( “game”, { time=500, effect = “crossFade”, params = { key1 = “value”, key2 = 10 } } )

Then in scene:show()

function scene:show( event )      local params = event.params      key1 = params.key1      key2 = params.key2 ...

Thats a great option for passing data that doesn’t need to be constantly updated.

  1. Composer variables. You can always add methods and member values to the composer object. You could do:

composer.coins = 0

in the transaction callback example above, instead of a function, you could just set the value directly:

composer.coins = composer.coins + 1

but you don’t know what all values we may be using in the Composer object or want to use in the future. This is an unsafe operation. But we built in two functions:  value = composer.getVariable( “variableName” ) and composer.setVariable( “variableName”, “someValue” ). This allows you to use composer to carry values between scenes.

  1. You could use Globals, but globals are not recommended for many reasons. But you can created a data table that can be required into each of your scenes to act like your own personal “global” table without the headache’s of globals.  See: http://coronalabs.com/blog/2013/05/28/tutorial-goodbye-globals/

This should give you plenty of ways for inter-module communications. But with regards to enterFrame listeners, physics, timers, transitions and such, those are best started in scene:show()'s “did” phase and cancelled/stopped/removed in scene:hide()'s “will” phase. You don’t want them running while the scene is transitioning to the next scene or continuing to run while the scene is off screen.

Finally the Engineers just added a way to create custom events and dispatch them. Check the latest daily build and the daily build documentation.

Rob

Think of a scene as complete app. It does all the work for what is currently on screen. In other words a Menu scene, a game setting scene or a game over scene doesn’t need to know anything about your game scene (* other than some data!). Your enterFrame listener, timers, physics, and objects are all best contained within the one scene.

Now some events, like back key handling on Android, or low memory events, in app purchases and such can be in main.lua and handle events that come in.

But Composer is really cool because you can call composer.getScene(“current”) from say an In App purchase transaction to get the current scene. If you’ve created functions in that scene that you add to the scene object you can then reference them elsewhere.

Lets say someone where your game.lua scene you define a function:

local coins function scene.handleBuyCoinsPurchase( numCoins )     coins = coins + numCoins end

Now in your in app purchase transaction listener you can do:

local function transactionCallback( event )     local transaction = event.transaction     local tstate = event.transaction.state     if tstate == "purchased" then           local currentScene = composer.getScene( "current" )           currentScene.handleBuyCoinsPurchase( 100 )    end    .... end

If there are data variables that need to be shared between scenes or app wide, there are multiple ways to do it.

  1. Pass paramters. composer.gotoScene() takes an options table that can include a child table that can contain key-value pairs. They are available in scene:create() and scene show:

    composer.gotoScene( “game”, { time=500, effect = “crossFade”, params = { key1 = “value”, key2 = 10 } } )

Then in scene:show()

function scene:show( event )      local params = event.params      key1 = params.key1      key2 = params.key2 ...

Thats a great option for passing data that doesn’t need to be constantly updated.

  1. Composer variables. You can always add methods and member values to the composer object. You could do:

composer.coins = 0

in the transaction callback example above, instead of a function, you could just set the value directly:

composer.coins = composer.coins + 1

but you don’t know what all values we may be using in the Composer object or want to use in the future. This is an unsafe operation. But we built in two functions:  value = composer.getVariable( “variableName” ) and composer.setVariable( “variableName”, “someValue” ). This allows you to use composer to carry values between scenes.

  1. You could use Globals, but globals are not recommended for many reasons. But you can created a data table that can be required into each of your scenes to act like your own personal “global” table without the headache’s of globals.  See: http://coronalabs.com/blog/2013/05/28/tutorial-goodbye-globals/

This should give you plenty of ways for inter-module communications. But with regards to enterFrame listeners, physics, timers, transitions and such, those are best started in scene:show()'s “did” phase and cancelled/stopped/removed in scene:hide()'s “will” phase. You don’t want them running while the scene is transitioning to the next scene or continuing to run while the scene is off screen.

Finally the Engineers just added a way to create custom events and dispatch them. Check the latest daily build and the daily build documentation.

Rob