Scene Management Issues

Working on managing the transition between a menu, a level, and then back to the level. In my game.lua file which runs the levels I load a bunch of different modules (player.lua, gem.lua, and floor.lua) which control various aspects of the level. I made it so that when the escape key is pressed composer.gotoScene(“menu”); is called. However, all of the modules are still loaded in the menu. I can tell because if the player stays in one spot for 5s or more they die and ~5s after the menu is opened I see my debug error message come up “player is dead!” which is called from floor.lua. So how do I manage scenes properly so that when I go to another scene all of the other modules are deactivated? My whole previous scene including physics, etc. still runs behind the menu but with no display.

Thanks in advance for any help

a couple things…

in your scene’s hide event ('s, either will or did) you should pause/stop your game. (can’t be more specific than that, you’ll have to figure out what that means in YOUR app - but at least remove event listeners, frame loops, cancel transitions/timers, etc - whatever it takes to make it go “dormant”.

in your scene’s destroy event you should remove all display objects (some of which may have been created during the create event, but also any subsequent)  some of this may happen automatically as the scene’s view is destroyed, but potentially some might not, if not in that view - best to try to do it all yourself manually just to be sure.

you may optionally, from the menu scene, call composer.removeScene() if you want to actually remove the game scene code from memory, which will dispatch that destroy event and destroy its view, and reissue a new create event next time it’s shown.  (you can only do this after the game scene is completely hidden/menu is completely shown)

In addition to what @dave has said above…

What I would do is add 2 functions to each of your modules (player.lua, gem.lua, and floor.lua) called start(), stop().  They will perform any start and stop code required - things like pausing player movement, etc.

Now when you want to show a (temporary) menu you would simply call player:stop(), enemy:stop(), etc and then when menu is hidden you can call player:start(), enemy:start() to continue where you left off.

I would then encapsulate those into gamePause() and gameResume() functions that call the respective stop() and start() functions and pause any timers, stop any transitions and start/stop physics.

Hope this helps.

Sorry if I wasn’t clear, but this is a main menu, not a pause menu. I want to basically get rid of the entire scene since player.lua, gem.lua, and floor.lua are still running behind the new menu scene. Also the display part is fine, I can’t see the previous scene since it’s all part of the scene group, however everything is still running in terms of the files, just invisibly

Also now was able to get the scene to clear with composer.removeScene(), however then it errors with “attempt to index instance.x, a nil value” in the player.lua. It’s still running the events in player.lua despite all of them having their listeners be removed via removeEventListener() in instance:finalize(), which isn’t being called. Before the code would keep running in the background of the main menu scene however now something is obviously happening to the player’s instance when transitioning to the menu scene because now it errors. I’ve also debugged it and the instance isn’t nil and it isn’t an empty table, but it’s lost a bunch of its parameters

Oh OK… ensure you are removing all references to player.lua.  I assume you have a player:destroy() that cleans everything player related down?  Have you got any timers or callbacks that maybe loading your modules again?

doesn’t matter what scene you go to - if you “leave” the game scene (for any reason) then you need to terminate its logic, clean it up, etc.   look for runtime listeners, particularly enterframe listeners, as those do not ever clean themselves up - you HAVE TO clean those up yourself.

if you leave it running, then it’ll still be running.

@Sphere Game Studios I’m using Tiled and hence ponytiled.lua which uses a map:extend() function to take object names from the loaded map and link them to a .lua file. It looks like this:

[lua]  function map:extend(…)
    local extensions = arg or {}
    – each custom object above has its own ponywolf.plugin module
    for t = 1, #extensions do
      – load each module based on type
      local plugin = require ((map.extensions or defaultExtensions) … extensions[t])
      – find each type of tiled object
      local images = map:listTypes(extensions[t])
      if images then
        – do we have at least one?
        for i = 1, #images do
          – extend the display object with its own custom code
          images[i] = plugin.new(images[i])
        end
      end 
    end
  end[/lua]

Therefore I don’t really have control over what’s loaded and what isn’t. Also, how would I call a player:destroy() function when I have no reference to when the player is leaving the level (via the escape key) except in the game.lua file?

Try this

-- Called when a key event has been received local function onKeyEvent( event )     if event.keyName == "escape" then --Add clean down code here end     -- IMPORTANT! Return false to indicate that this app is NOT overriding the received key     -- This lets the operating system execute its default handling of the key     return false end -- Add the key event listener Runtime:addEventListener( "key", onKeyEvent )

Okay. But then what constitutes “clean down code”?

“Clean down code” is the complete reversal of everything you have created in your game scene.  This is all references (code and display), timers, listeners and enterframe events.

But then how would I call these if I don’t even have reference to the files that the player, gem, and floor logic is in?

I’m not sure as I’ve never used the library.  There must be docs for it?

They’re extremely limited and although the Sticker-Knight exemplar is able to do what I’m trying to get done, I can’t seem to get much useful out of looking through it

Finally figured it out after some puzzling. This may not be the ideal way, but I basically was able to set a variable to the player via game.lua and check if that’s true (which is by default not and then set to true when the escape key is pressed) and then if so call instance:finalize(). Thanks @Sphere Game Studios and @davebollinger for your time and support

Hey glad you got there in the end mate

So now I’m able to go between the main menu and the one level but I can’t seem to get it to work properly. Although the level appears to be reset some objects don’t display correctly and the physics and collisions are messed up for the player. I’m currently using composer.goToScene() and then composer.removeHidden()

After some debugging, etc. I’ve figured out that basically the player is becoming misaligned in terms of their y-coord which is screwing up all of my collision checks since they are only recorded if the player is aligned to the 32x32 grid. You can tell in the images below as well where the player becomes misaligned because the most recently passed-over tile doesn’t disappear and the player gets stuck in the block in front of them in the one on the right (which occurs after reloading the scene):

IV8nM5v.png

I’m still not really sure why this is happening. I’ve destroyed the previous scene in the menu scene (which it goes to first) via composer.removeHidden() and then when it reloads it doesn’t function properly. All of my tiles a static sensors except for the player which is a dynamic body with all of its physics properties set to 0. The gravity is also 0 and I checked that it still is (or at least thinks it is) when reloaded be printing that value to the console. Been trying to use Sticker-Knight as an example but it hasn’t given me any insight yet into why this isn’t functioning properly.

If anyone wants to hazard a look at my code (here: https://hastebin.com/oxopezewuh.lua) that’d be great and any other suggestion would help too. Haven’t commented the code but it is pretty self-explanatory based on variable names

Try looking into scene:destroy:

https://docs.coronalabs.com/api/event/scene/destroy/index.html

The problem could be in the frameEvent function in floor.lua. Maybe your math is wrong?