FAQ for AppState

Hello,
as I understand from reading the AppState docs, you should “setEnabled(false)” / “setEnabled(true)” to Pause / Unpause a game.
Only if the currently running game should be aborted and a new one starts, you would “detach” and (re-)“attach” the PlayingGameState.

Somehow this is not reflected by the FAQ wiki, where I read:
"
How do I pause/unpause a game?

You split up your application into several AppStates and implement the setEnabled( ) methods for each state. Then you create, for example, a GameRunningAppState and a GamePausedAppState. GamePausedAppState’s job is to attach all your AppStates that contain the logic and GUI of the pause screen, and to detach all the AppStates that contain logic and GUI of the running game. GameRunningAppState does the opposite. By attaching one or the other to the game, you switch between the paused and unpaused states.
Learn more: Application States.
"

Typically this would lead to a “cleanup( )” call, where you would remove all spatials that you’ve added to the root node when you started the game.
Maybe I see something wrong here, and maybe you COULD implement it in the way that the FAQ suggests.
I will soon look into projects like “Monkey Zone” to find out how others have programmed their state logic.
But the first thought was: That’s wrong, I would enable/disable instead of attach/detach.

Ach, stupid me.

The text states “detach all states that contain logic and GUI”

  • well this might be okay, I guess. If you do it right.
    I would still prefer enable(false) over detach.

You mean you would use setEnable(false) to pause instead of detaching?

So would I.

1 Like

Lemur has a BaseAppState class that may soon make it back to core. It handles the enable/disable dance for you (enable if attached and enabled, disable if detached or disabled, etc.)

http://code.google.com/p/jmonkeyplatform-contributions/source/browse/trunk/Lemur/src/com/simsilica/lemur/event/BaseAppState.java

In this, you override enable() and disable() to do your adding/removing from the scene. I typically use initialize() to create some stuff ahead of time and then use enable() to attach it… but it really depends on the situation. Sometimes I also register key listeners and stuff in initialize (and then remove them in cleanup()) if I want the app state to be enabled by keys.

…but mostly I do that stuff in enable()/disable().

2 Likes

i’ve written similiar “advanced” simple appstates/controls that try to intelligently and automatically handle enabling. TBH though I find it more of an annoyance than anything else because the behavior you want when initializing/cleaning up is very implementation specific, and you end up with a lot of excess checks by the implementing class (and any cascaded calls to setEnabled()) to handle situations that this sort of continence superclass is supposed to make easier. (preventing issues of calling setEnabled() when already enabled, calling setEnabled() when not initialized…)

I think ultimately, you end up with less code if you just make your appstate such that they handle their own setEnabled (as done in using AbstractAppState), its not hard to add if(setEnabled == isEnabled()) return; for states that break when calling enabled twice, and its not hard to add if(enabled) setEnabled(true) in states where enabled cant be called until after initialization.

(edit: of course no one would be forced to use it if BaseAppState was put in the core, I’m just stating i think it would cause confusion and frustration to newcomers if it was to be recommended over AbstractAppState)

attach/detach and enable/disable do essentially the same: start/stop an AppState.

As noted, you can use that to unpause/pause a game, but there are more things - demo mode, cutscenes, stopping and saving the game. You could also use them to control in-game activation and deactivation logic - windmills, machines, autopilot vs. manual craft control.

Override attach/detach to do heavyweight stuff: Loading/forgetting assets, setting up database connections, calculating path graphs, or whatever takes a while.
Override enable/disable to do lightweight stuff: starting or stopping an animation, inserting stuff into the scenegraph or taking it out.

…and I know we are using “attached/detached” to indicate “initialize/cleanup” but just in case someone else reading this doesn’t understand that:

Never override stateAttached()/stateDetatched() *.

  • Standard caveat: Unless you can argue why you specifically need that behavior over initialize/cleanup… because it’s almost always wrong to override stateAttached and stateDetached.
@icamefromspace said: (edit: of course no one would be forced to use it if BaseAppState was put in the core, I'm just stating i think it would cause confusion and frustration to newcomers if it was to be recommended over AbstractAppState)

I’m not sure what you think BaseAppState is doing. Essentially all it does is make sure that enable() and disable() are called appropriately. You are welcome to do it yourself but it’s really easy to get wrong.

In initialize() you have to check and see if you are enabled or not and call enable(). In setEnable() you have to check to see if you are initialized or not and call enable or disable as appropriate (if you are initialized, otherwise don’t.)

The whole point is to make sure that the lifecycle is consistent:
initialize()
enable()
disable()
terminate()

And that calling setEnabled() outside of being initialized only sets the flag.

It’s not doing anything more advanced than that. I’ve seen so many people get their states wrong extending AbstractAppState. It’s a nearly do nothing class that has no real point.

1 Like

I’m not up in arms against it or anything (anyone can just implement app state if they dont like it), it is a good way to enforce logical behavior. I’m just saying the end result is a lot of extra public and protected methods whose only description is “never call this method” and the ones youre supposed to call youre not supposed to override. It’s just not an intuitive way to code (atleast for me). Id rather just look at the code is being called than have invisible hands preventing me from what I want to do or try to guide me into their way of doing things.

if anything i think app state should be going the other way, instead of becoming more structured they should become less, setEnabled() and isEnabled() should be removed from the AppState interface and if I want setEnabled() behavior on my appstate I can just call “if enabled return;” in my update method on my own. (similiar to how Controls are).

For instance, what if I want setEnabled() to “pause” the state, but I still want the appstate to receive calls on update. On my ConsoleAppState plugin my setEnabled() method actually just throws an operation not supported exception.

@icamefromspace said: I'm not up in arms against it or anything (anyone can just implement app state if they dont like it), it is a good way to enforce logical behavior. I'm just saying the end result is a lot of extra public and protected methods whose only description is "never call this method" and the ones youre supposed to call youre not supposed to override. It's just not an intuitive way to code (atleast for me). Id rather just look at the code is being called than have invisible hands preventing me from what I want to do or try to guide me into their way of doing things.

if anything i think app state should be going the other way, instead of becoming more structured they should become less, setEnabled() and isEnabled() should be removed from the AppState interface and if I want setEnabled() behavior on my appstate I can just call “if enabled return;” in my update method on my own. (similiar to how Controls are).

For instance, what if I want setEnabled() to “pause” the state, but I still want the appstate to receive calls on update. On my ConsoleAppState plugin my setEnabled() method actually just throws an operation not supported exception.

We will have to agree to disagree. If you don’t want app state lifecycle then you are free to not use them. What you want amounts to little more than just calling your own code in simpleUpdate(). In fact, it really bugs me that control doesn’t have disable/enable without my implementing it myself and it super-duper-duper bugs me that there is no way to know when a control dies. I’d like to be able to disable components without changing the component order. A standard and enforced way to do this would be nice.

Order is often important for app states, too.

Regarding your first comments…
I think you must be looking at a different class. The only methods I added were some protected ones and I made the existing public methods final. Too many users were forgetting to call super.initialize(), etc… and it’s often convenient to have Application in the cleanup() method and I didn’t want to break the API.

Half to 2/3s of my app states don’t even have an update method. They do all of their processing in initialize()/enable()/disable()/cleanup(). And there is more to disabling a state than just not calling update anymore. Otherwise, I suggest you are doing it wrong or have bugs yet-to-be-found.

Maybe you mean the convenience methods for getApplication(), getStateManager(), and getState()?

@icamefromspace said: For instance, what if I want setEnabled() to "pause" the state, but I still want the appstate to receive calls on update. On my ConsoleAppState plugin my setEnabled() method actually just throws an operation not supported exception.

Then the app state is still enabled. What would “pausing” mean if update is still called. There is some other method custom to your state in that case that is not related to enabled.

“What if I wanted to initialize my app state but not have initialize() called?” You see how it kind of doesn’t make sense to ask a question like that.

@pspeed said: We will have to agree to disagree. If you don't want app state lifecycle then you are free to not use them. What you want amounts to little more than just calling your own code in simpleUpdate(). In fact, it really bugs me that control doesn't have disable/enable without my implementing it myself and it super-duper-duper bugs me that there is no way to know when a control dies. I'd like to be able to disable components without changing the component order. A standard and enforced way to do this would be nice.

We’ll have to agree to disagree about the use of enabled, but I certainly agree with you about the lack of spatialDetached(). You can atleast detect your first update() call, but its psychically impossible to detect the last update() because of the obvious reason. (having both spatialAttached() and spatialDetached() would be nice though). I suspect there must be some technincal difficulty thats preventing anyone from simply adding this feature or itd probably already be done :smiley:

Regarding your first comments... I think you must be looking at a different class. The only methods I added were some protected ones and I made the _existing_ public methods final. Too many users were forgetting to call super.initialize(), etc... and it's often convenient to have Application in the cleanup() method and I didn't want to break the API.

Half to 2/3s of my app states don’t even have an update method. They do all of their processing in initialize()/enable()/disable()/cleanup(). And there is more to disabling a state than just not calling update anymore. Otherwise, I suggest you are doing it wrong or have bugs yet-to-be-found.

Maybe you mean the convenience methods for getApplication(), getStateManager(), and getState()?

I consider protected methods just as bad as public, since protected methods can become public simply just be calling them public in the subclass. (thus must be maintained like theyre public), it for instance is possible to call enableState() but it doesnt provide the behvaior youre probably desiring (which is setEnabled(true)). ESPECIALLY if youre in the case I have with ConsoleAppState (explained below)

Then the app state is still enabled. What would “pausing” mean if update is still called. There is some other method custom to your state in that case that is not related to enabled.

In the case of my ConsoleAppState, “enabled” is for use with the keybindings, i made a method setVisible() tht more clearly explains whats happening. I guess I could have better explaining myself by saying “what if i dont want my appstate to have setEnabled(false)”. Theres nothing internal in the engine that uses enabled (AFAIK) its just in the interface so people can always be able to expect for it to be there without having to typecast, even if programmer of the app state might have @Override isEnabled(){return true;}. The typecasting shortcut is defeated by the need to read the code of the appstate to see what it does.