Jump to content

[TOPIC: topicViewTemplate]
[GLOBAL: userSmallPhoto]
Photo

Going from overlay scene to regular scene in composer
Started by Divergent Monkey Jan 11 2017 02:16 PM

- - - - -
16 replies to this topic
composer scene overlay reload reset

Best Answer roaminggamer , 12 January 2017 - 12:13 PM

1. Download this file:

 

https://github.com/roaminggamer/CoronaGeek/raw/master/Hangouts/composer_scene_manager.zip

 

 

2. Run example 12_rebuild_playgui

 

 

3. Review the sample and pay particular attention to these files:

  • ifc/playGUI.lua
  • ifc/gameOverOverlay.lua
  • scripts/game.lua

[TOPIC CONTROLS]
This topic has been archived. This means that you cannot reply to this topic.
[/TOPIC CONTROLS]
[modOptionsDropdown]
[/modOptionsDropdown]
[reputationFilter]
[TOPIC: post.html]
#1

Divergent Monkey

[GLOBAL: userInfoPane.html]
Divergent Monkey
  • Contributor

  • 356 posts
  • Corona SDK

I have the following composer structure  in ny game:

 

playGame (regular scene) --> youDiedPleaseTryAgain (overlay scene) --> playGame (regular scene)

 

When the user touches the retry button in youDiedPleaseTryAgain, the following code executes:

composer.hideOverlay()
composer.removeScene("playGame")
composer.gotoScene("playGame")

The reason that I want to remove/recreate playGame is to avoid having to remember to reset everything, seems more safe to just recreate.

 

At "removeScene", only the destroy() function in playGame is called, which is normal I guess. But at "gotoScene" the hide() function in playGame is called and NOT the create() function as I would have guessed. The problem is that since playGame no longer exists, I get errors for trying to access stuff that are nil in the hide() function.

 

Why is the hide() function in playGame called at all? How should I reset a scene from an overlay like in the example above?



[TOPIC: post.html]
#2

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,641 posts
  • Corona SDK

If you're showing the 'playGame' scene, even if you have an overlay showing too, you can't remove the scene and then go to it. 

 

You have to go to another scene before going back to 'playGame' will operate correctly.  

 

If you want to stay in the same scene, you'll have to write your own functions destroy and re-create the content and call them directly, OR try calling the scene methods directly ( I don't really suggest the latter because I've never used this technique and I don't know the drawbacks/gotchas).

 

Nonetheless, you manually call a scene's methods from the overlay you could try this:

local composer = require( "composer" )
local playGame = composer.getScene( "playGame" )

-- call any other methods you need, but this is the basic way to do it.

playGame:destroy() -- method name must match the one you used when defining the scene
playGame:create() -- method name must match the one you used when defining the scene



Edited by roaminggamer, 11 January 2017 - 02:55 PM.


[TOPIC: post.html]
#3

Divergent Monkey

[GLOBAL: userInfoPane.html]
Divergent Monkey
  • Contributor

  • 356 posts
  • Corona SDK

Ok, thanks!

 

I would have thought that the situation that I described is quite common, i.e. getting an overlay at the end of a level and being able to go directly back to the game to replay the level. I have many games on my iPhone right now that work like that (perhaps developed using another framework than Corona). Shouldn't a "scene tool" like Composer be able to handle that in an out-of-the-box manner?



[TOPIC: post.html]
#4

Divergent Monkey

[GLOBAL: userInfoPane.html]
Divergent Monkey
  • Contributor

  • 356 posts
  • Corona SDK

I tried this:

 

playGame (regular scene) --> youDiedPleaseTryAgain (overlay scene) --> dummy(regular scene) --> playGame (regular scene)

 

where dummy only has the following in its show() function, nothing else:

composer.removeScene("playGame")
composer.gotoScene("playGame")

In playGame there is a frame listener that is added in the show() function and removed before youDiedPleaseTryAgain is called.

After doing the remove/goto in dummy, the frame listener in playGame got registered twice (sounds weird, I know), which in turn caused all sorts of problems. The only way I got it to work was to add a timer with a small delay between remove and goto. I don't understand why since the frame listener was removed well before even youDiedPleaseTryAgain was called...

 

I still think that having an overlay at the end of the scene (like in Angry Brids Space) is something that Composer should be able to handle. Or am I implementing it all wrong?



[TOPIC: post.html]
#5

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,641 posts
  • Corona SDK

Ok, thanks!

 

I would have thought that the situation that I described is quite common, i.e. getting an overlay at the end of a level and being able to go directly back to the game to replay the level. I have many games on my iPhone right now that work like that (perhaps developed using another framework than Corona). Shouldn't a "scene tool" like Composer be able to handle that in an out-of-the-box manner?

 

I'm not a big fan of questions like this, because you're basically saying.  It doesn't work the way I want it to, so it must be Corona's fault.

 

The problem here is your code isn't written to handle cleaning up the scene and re-building it without destroying the scene group. 

 

(Recall suggestion one above)

 

 

 you'll have to write your own functions destroy and re-create the content and call them directly

 

This is why I always encourage people NOT to start with composer till they can write a module that creates the 'scene', destroys the scene, and re-builds the scene. Then I tell them, "Call the module from your composer scene, but let your module do all the work."

 

I'll respond later with a simple example demonstrating this concept.  Right now I'm catching up on e-mails and don't want to stop for this.



[TOPIC: post.html]
#6

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,641 posts
  • Corona SDK

PS - If I sound snippy, don't be offended.  I realize what you're trying to do, and I understand where the confusion is coming from.

 

Composer.* is a fine piece of code, you simply have to use it correctly to get the results you desire.

 

I'll help a bit more later.



[TOPIC: post.html]
#7

Divergent Monkey

[GLOBAL: userInfoPane.html]
Divergent Monkey
  • Contributor

  • 356 posts
  • Corona SDK

It seems I basically have two choices:

  1. Refactor the playGame scene so that I don't need to destroy it to replay a level or go to the next level. I tried this and it worked fine except that display objects used in one level still existed in the sceneGroup (from self.view) in the next level, causing different problems. I couldn't find a way to get rid of them without manually fiddling with sceneGroup, which I am not sure is a good idea. I also tried to put these objects in a separate display group and delete them in the hide() function but since they were not in the sceneGroup, they were displayed on top of everything else, inlcluding the overlay scene.
  2. Write my own methods for creating and destroying scenes, as you suggest.

Again, I would assume that what I want to achieve is pretty common since a lot of level based games have this "scene sequence". Generally speaking, what would be the best practice to do this?



[TOPIC: post.html]
#8

Divergent Monkey

[GLOBAL: userInfoPane.html]
Divergent Monkey
  • Contributor

  • 356 posts
  • Corona SDK

My preferred solution would be not having to destroy the playGame scene at all and simply making it work by reseting all game elements to an initial state when the level starts. The only problem here is that the (level specific) display objects from the previous scene remain in self.view since the scene has not been destroyed before restarting the level, and thus causing problems in the next level. However, if I put them in another display group instead to get around that, they are always displayed on top (like all display objects not in self.view), which is not good either.

 

This is basically the problem I need to solve...



[TOPIC: post.html]
#9

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,641 posts
  • Corona SDK

  Best Answer

1. Download this file:

 

https://github.com/roaminggamer/CoronaGeek/raw/master/Hangouts/composer_scene_manager.zip

 

 

2. Run example 12_rebuild_playgui

 

 

3. Review the sample and pay particular attention to these files:

  • ifc/playGUI.lua
  • ifc/gameOverOverlay.lua
  • scripts/game.lua


[TOPIC: post.html]
#10

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,641 posts
  • Corona SDK

Note: If you have objects from sceneA lingering in sceneB, you didn't put them in the scenegroup (or or child of that group) owned by sceneA.  This is a common mistake.



[TOPIC: post.html]
#11

Divergent Monkey

[GLOBAL: userInfoPane.html]
Divergent Monkey
  • Contributor

  • 356 posts
  • Corona SDK

I have downloaded it and I will analyze it now, let me get back....

 

About your second posting: what I meant was that when I go back to the playGame scene the second time (after completing a level and continuing with the next via the overlay scene), the display objects are still in the sceneGroup causing problems. In other words the first time I call playGame some scene specific objects are inserted into sceneGroup. When I have finished the level and want to play the next level, I call playGame a second time. At this point, all display objects from the first time are still in the sceneGroup (together with the new objects from the second time). As I said, one solution would be not to put them in the sceneGroup at all but in another displayGroup which I delete manually after each level. However, then all these object are displayed on top of everything else....



[TOPIC: post.html]
#12

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,641 posts
  • Corona SDK

You should always manage your own group hierarchy and simply add that hierarchy as a child of sceneGroup
 
In my client and personal games I never place anything directly in scenegroup.  Instead I do something like this:
local layers

function scene:create( event )
   sceneGroup = self.view
 
   -- Create some rendering layers
   layers = ssk.display.quickLayers( sceneGroup, 
      "underlay", 
      "world", 
         {
            "background", 
            "content", 
         }, 
         "buttons",
         "overlay" )

   newImageRect( layers.underlay, centerX, centerY, 
              "images/interface/protoBack.png", 
              { w = 380, h = 570, rotation = (isLandscape) and 90 or 0 } )

   easyIFC:quickLabel( layers.buttons, "Credits", centerX, 30, gameFont, 30 )

   easyIFC:presetPush( layers.buttons, "default", 55, h - 25, 100, 40, "Back", onBack )
end

The above code creates a display group hierarchy and places it in the sceneGroup


Personal Request: I have real difficulty reading wall-of-text posts.  Can you please use paragraphs in your posts.  
 
I want to help, but I have to guard my time jealously.  So, anything that takes multiple readings to understand gets cut.

Edited by roaminggamer, 12 January 2017 - 01:31 PM.


[TOPIC: post.html]
#13

roaminggamer

[GLOBAL: userInfoPane.html]
roaminggamer
  • Corona Geek

  • 7,641 posts
  • Corona SDK

Followup:  In examples on the other hand I do place things in 'sceneGroup' because it keeps the example short and easy to read.  
 
It just isn't what I consider a good practice for for anything but the most trivial real apps and games.

 

Note: 'trivial' is not a derogatory term here.  It is an assessment of complexity.


Edited by roaminggamer, 12 January 2017 - 01:44 PM.


[TOPIC: post.html]
#14

Rob Miracle

[GLOBAL: userInfoPane.html]
Rob Miracle
  • Moderator

  • 26,622 posts
  • Enterprise

You can't remove the scene you're in. An overlay scene is still dependent on it's parent scene so you can't remove it. Simply turn your overlay into a regular scene, go to the game over scene, remove the game and go back.

 

Rob



[TOPIC: post.html]
#15

Divergent Monkey

[GLOBAL: userInfoPane.html]
Divergent Monkey
  • Contributor

  • 356 posts
  • Corona SDK

@Rob: thanks!

 

@roaminggamer: I looked at your files and I now understand what you mean. I have refactored my code so that I put all the "level specific" objects in a separate group, which I then add to the sceneGroup. I also made custom functions to create and destroy the game scene (like in your code). It works like a charm! :o) Thank you very much for all your help, I really appreciate it! You should be on the Corona payroll for the service you do to the community in these forums...



[TOPIC: post.html]
#16

nick_sherman

[GLOBAL: userInfoPane.html]
nick_sherman
  • Corona Geek

  • 1,960 posts
  • Corona SDK

The simple solution is to create a blank composer scene called loading that immediately purges and reloads the scene it just came from.

[TOPIC: post.html]
#17

Divergent Monkey

[GLOBAL: userInfoPane.html]
Divergent Monkey
  • Contributor

  • 356 posts
  • Corona SDK

@nick_sherman: i tried that but that gave me weird effects with listeners that got registered twice etc. It worked when I added a delay of 100 ms but it did not seem like a very safe solution. Doing what roaminggamer suggested did the trick...




[topic_controls]
[/topic_controls]