Understanding AppStates - Game Screen / Menu Screen

Hi,



I’m struggling to understand how I should go about using AppStates. I would like to have a menu screen (using nifty), and a separate game screen.



The way I imagine it working is something like this:


  1. Main application class has two AppState member variables. One for the menu screen and one for the game screen.
  2. The menu screen AppState is attached to the stateManager during simpleInitApp.
  3. The menu screen AppState handles a click on a button, which sets the “next action” status into the object. E.g. User clicks “new game”, the menu screen AppState stores that outcome.
  4. During simpleUpdate in the main application class, it checks the menu screen’s AppState for a new game outcome, and then detaches the menu screen AppState, and attaches the game screen AppState.



    I have a number of questions I’d like to ask:


  5. Firstly, is it the right approach to use AppStates, or is there something I’m missing?


  6. Do I need to create two completely separate root nodes, gui nodes and so on? Or will attaching/detaching the appropriate AppState show/hide it?


  7. Essentially, I’m after some advice on best practice!



    I’m very new to jme3 (I’m really enjoying it!), and this is the first time I’ve posted, so I apologise if I’ve missed something plainly obvious :]



    Thanks,



    Tom

Well, since AppState is kinda just an abstraction for update and render methods, you actually don’t have to put stuff in AppStates. Using nifty gui, you won’t have to put anything in those methods, so you can just initialize nifty, attach it to gui node and handle events in special class (or classes), which doesn’t have to be exactly AppState (but must be ScreenControler). For a game, if you have a simple setup, you can probably put everything also in SimpleApplication. AppState comes in use imho for more hardcore setups, if you have for example different game modes and each one is behaving differently through time. :slight_smile:

2 Likes

Though there is a lot of benefit in having your ScreenControllers also be app states. This is what Mythruna does and it makes sure that my click handlers, etc. have access to all of the stuff they need.



I recommend having an app state for the main menu and one for the game… and then doing nothing on simpleUpdate.



simpleInit would create your main menu app state and attach it to the state manager. Then it would initialize nifty and pass it as a screen controller when loading the XML.



Your main menu app state could have an option to start the game that calls a method on your main menu app state. This method can then instantiate and attach the game app state right there.



If you want to switch back and forth then you could create and add both of them during simpleInit and just setEnabled(false) the game state. Main menu can enable it and disable itself and whatever menu key can reverse that to bring back the menu.



In that case, you want to do your showing/hiding/attaching/removing scene elements, etc. in the setEnabled() as appropriate.



You don’t have to keep references to your app states because they are easy to look up by class.



In Mythruna, I have some helper app state base classes and a toggle app state helper class (has child app states and makes sure only one is enabled at a time) to make this state switching easier.

2 Likes

Note: I could explain more about the base class and helper classes if needed.

Thank you both for the great, and fast responses.



@InShadow - I see what you mean. I did take this approach initially, but I started to get the feeling that the main application class was just going to get so full of code, that it’d be a nightmare to maintain! :slight_smile:



@pspeed - Thanks a lot. I do like the idea of using separate app states. In fact, I started to go down this route too - I created an app state base class, but got stuck when it came to having each app state draw to the screen. I created a blue box in the menu state, and a red box in the game state, but despite attaching/detaching… they would both draw to the screen… then stuff just started to get messy. To be honest, it was late, and I was probably missing something fairly obvious. For example, I wasn’t calling setEnabled.


pspeed said:
Note: I could explain more about the base class and helper classes if needed.


I would be really interested and appreciative of any more advice/explanation you could offer regarding the base and helper class, thank you. :]

I've literally just found this post about app states, which appears to do what I'm after: http://hub.jmonkeyengine.org/groups/development-discussion-jme3/forum/topic/appstate-example/ (I did search before posting, but didn't find this!).

I'll see if I can replicate a similar kind of behaviour. The goal for me is to "get it working", then refactor it to how I would like it to be structured.

Thank you.

There is no magic in AppStates, really. When they are attached/enabled then you need to do the “adding” of stuff and when they are detached/removed then they need to do the “unadding” to make stuff go away.



My base class tries to manage this so that I get an enable() and disable() and the base class manages when to call that. So if I enable an unattached app state then nothing happens. If it is attached and enabled then I get enable() and I see disable() whenever it is detached or setEnabled(false) is called while attached. That way I don’t have to worry so much about it.



I can hook into initialization to setup the one-time stuff (materials, etc.) and then use enable() and disable() to manage the app state specific stuff.

1 Like

I see. I think my misunderstanding was: “if an AppState is detached, the elements within it are removed from the screen automatically”.



So to be clear, this is not the case. If I want to remove elements from the screen, the AppState being detached would have to handle that when it is being detached?



Thanks a lot for your help. I do have further questions, but I will have a look at the docs and see if I can answer them myself. :slight_smile:



Cheers.

Yeah… the AppState stuff has no idea what you added what you added in your app state. It’s up to you to manage it.



Some day I should contribute my app state base classes.

1 Like