Switching between collections (SOLVED)

As I continue the process of creating my first game with Defold I now have the following

A bunch of collections

  1. Splash - the splash screen
  2. Game - where all the Game action occurs
  3. Gameover - tells the user that they failed to complete the game within the allotted constraints with a “Play Again” button
  4. Leaderboard - shows the user their current achievements etc, again with a “Play Again” button

My bootstrap collection is called “main” and does little more than marshall movements between the other collections via a clutch of collection proxies and a script. I am now testing out the process of switching between collections and have found issues I do not understand

The Main script

function init(self)
math.randomseed(os.time())
msg.post("@render:", "use_stretch_projection", { near = -1, far = 1 })
msg.post(".", "acquire_input_focus") 
    --collections loaded through proxes do not respond to input unless this is done too

msg.post("/goMain#coproGameOver","load")
msg.post("/goMain#coproGameOver","enable")
   --purely as an experiment I am loading the GameOver collection for starters
   --goMain is the name of my Main collection
   --copro# are the various collection proxies defined in main
end

function final(self)
msg.post(".", "release_input_focus") 
    --only really happens when the app is shut down but feels like good practice 
    --to give back what you took in the first place
end

function on_message(self,message_id,message,sender)
  if (hash("play_again") == message_id) then 
print("Play Again!") 
msg.post("/goMain#coproGameOver","disable")
msg.post("/goMain#coproGameOver","unload")
   --I would be inclined to simply do this from the Gameover script but am doing it via a 
   --message back to the Main script just to follow what is shown in Defold docs
end

end

My GameOver collection loads correctly. I interact with by tapping on the Play Again button there. The relevant bit of code

function on_input(self,action_id,action)
  if (((CONSTS.HASH_CLICK == action_id) or (CONSTS.HASH_TAP == action_id))	and action.pressed) 
   --I define strings etc up front rather than scattering them **raw**  all over the place
  then
     if ((483 > (math.abs(action.x - 720))) and (146 > (math.abs(action.y - 1000)))) then
      --a small check that it was the button that was in fact clicked/tapped
      msg.post("main:/goMain#main_script","play_again")
     --send a message back to the master script in Main
     end 
  end 

What I find bizarre at this point is the message I get back when I do actually tap the “Play Again” button in the Gameover collection that IS on display. Here is what it says

The collection /collections/gameover.collectionc could not be disabled since it is not enabled. Message ‘disable’ sent from main:/goMain#main_script to main:/goMain#coproGameOver.
ERROR:GAMESYS: The collection /collections/gameover.collectionc could not be unloaded since it was never loaded. Message ‘unload’ sent from main:/goMain#main_script to main:/goMain#coproGameOver.

In a word - why?

Are you sure you’re not sending the “play_again” message twice?

1 Like

Yes, that was it - not quite sure why one tap on the Play Again button is resulting in two input events both with action.pressed set. However, ensuring that only one message is sent does the trick.

What I don’t understand from the Defold docs though is this - why bother with sending messages back to the main script. I can quite simply disable and unload the now unrequired collection directly from within its own script

msg.post("main:/goMain#coproGameOver","disable")   			 
msg.post("main:/goMain#coproGameOver","unload")
1 Like

From the Input Manual:

MOUSE_BUTTON_LEFT (or MOUSE_BUTTON_1 ) input actions are sent for single touch inputs as well .

So your touch is probably sending two events—one for each action. You only need the multi-touch input binding if you’re actually using multiple touches (or only use the multi-touch binding if you don’t want to support mouse input at all).


Is that actually in the docs somewhere?

You are right. The point of the message passing system is that you can send a message from anywhere to anywhere else, and the address of an object never changes.

The reason to use a separate script is organization. Sending messages from who-knows-where to mess with root level objects can easily cause you headaches later on. Also, maybe there will be more to it than just sending “unload”. Maybe, whenever you unload a collection you want to do some sort of transition, or you want to enable some menu objects, or save some data…Duplicating that code in different places would make it a nuisance to maintain.

FYI, you don’t always need to disable a proxy before you unload it. You only need to call “unload”.

2 Likes

The reason to use a separate script is organization. Sending messages from who-knows-where to mess with root level objects can easily cause you headaches later on. Also, maybe there will be more to it than just sending “unload”. Maybe, whenever you unload a collection you want to do some sort of transition, or you want to enable some menu objects, or save some data…

Yes, fair point. Thanks

1 Like