# Application States

`com.jme3.app.state.AppState` is a customizable jME3 interface that allows you to control the global game logic (game mechanics). To control the behaviour of a type of Spatial, see Custom Controls instead – both can be used together.

## Use Case

There will be situations during your game development where you think:

- Can I group a set of input handler settings, and activate and deactivate them all in one step? (e.g. mouse and key inputs are handled different in-game versus in the main menu.)
- Can I group a bunch of nodes and swap them in and out in one step? (e.g. the in-game scene, versus a character editor, versus a Captain's Quarters screen)
- Can I define what happens while the game is paused/unpaused, and toggle that in one step?
- Can I wrap up one set of game mechanics and switch it on and off in one step? (e.g. a conditional block that takes up a lot of space in my update loop)
- Can I package all of the above that belongs in-game, and also everthing that belongs to the main menu, and switch between these two "big" states in one step?

Yes you can! This is what AppStates are there for. A game state can be a subset of class fields (game data), GUI elements and their interactions, a subset of input handlers, a subset of nodes in the simpleInitApp() method, a subset of actions that you branch to in the simpleUpdate() loop, a set of AppStates and Controls – or combinations thereof.

Each AppState is such a grouped subset of such game states. Each AppState has hooks that let you define what happens to this set in the following situations:

- the AppState is initialized: You load and initialize game data, InputHandlers, AppStates and Controls and attach nodes.
- the AppState is cleaned up: You save the game state, unregister Controls, AppStates and InputHandlers, and detach nodes.
- the AppState is temporarly disabled/enabled (paused/unpaused): You toggle a boolean to skip certain actions of the update loop, you display a paused screen GUI, and change the input handlers.

Tip: You can create AppStates that enable and disable sets of other AppStates, e.g. InGameState versus MainScreenState.

## Usage

To implement game logic:

1. You define a custom AppState and implement its behaviour in the AppState's update() method.
   - You can pass custom data as arguments in the constructor.
   - The AppState has access to everything inside the app's scope via the Application `app` object.
2. Attach all AppStates to your application's AppStateManager (`stateManager.attach(myAppState);`), and activate and deactivate the ones you need.
3. Create one AppState for each set of game mechanics.

When you add several AppStates to one Application and activate them, their init methods and update loops are executed in the order in which the AppStates were added.

## Examples

JME3 comes with a BulletAppState that implements Physical behaviour (using the jBullet library). You, for example, could write an Artificial Intelligence AppState to control all your enemy units. Existing examples in the code base include:

- controls physical behaviour in PhysicsControl'ed Spatials.
- an example of a custom AppState

## AppState

The AppState interface allows you to initialize sets of objects, and hook a sets of continously executing code into the main loop.

AppState Method | Usage
--- | ---
stateAttached(asm) stateDetached(asm) | The AppState knows when it is attached to, or detached from, the AppStateManager, and triggers these two methods. Here you implement what happens then.
initialize(asm,app) | The RenderThread initialized the AppState and then calls this method. Here you implement initSimpleApp()-style initialization code.
isInitialized() | Your implementations of this interface should return the correct respective boolean value.
setActive(true) setActive(false) | Temporarily enables or disables an AppState.
isActive() | Test whether AppState is enabled or disabled. Your implementation should consider the boolean.
update(float tpf) | Here you implement the behaviour that you want to hook into the simpleUpdate() loop.
cleanup() | Called when when the AppState is de-initialized. Here you implement what clean-up code for this state.
render(RenderManager rm) | Renders the state, plus your optional customizations.
postRender() | Called after all rendering commands are flushed, including your optional customizations.

## AbstractAppState

The AbstractAppState class already implements some common methods and makes creation of custom AppStates a bit easier: isInitialized(), setActive(), isActive(), cleanUp(). Just extend it and override the remaining AppState methods. Definition:

    public class MyAppState extends AbstractAppState {
        private Node x = new Node("x"); // some class field
        private SimpleApplication app;

        public Node getX(){
            return x;                    // implement custom methods for this field
        }

        @Override
        public void update(float tpf) {
            x.doSomething();             // call some methods here
        }

        @Override
        public void initialize(AppStateManager stateManager, Application app) {
          super.initialize(stateManager, app);
          this.app=(SimpleApplication)app;
          app.doSomething();             // call some methods elsewhere
        }
    }

## AppStateManager

The com.jme3.app.state.AppStateManager holds the list of AppStates for an application. AppStateManager ensures that active AppStates are updated and rendered. When an AppState is attached, AppStateManager calls its stateAttached() method. When an AppState is detached, AppStateManager calls its stateDetached() method. There is one AppStateManager per application. You can attach several AppStates to one AppStateManager, but the same state can only be attached once.

AppStateManager Method | Usage
--- | ---
hasState(s) | Is AppState s attached?
getState(Class<T> stateClass) | Returns the first state that is an instance of a subclass of the specified class.

The AppStateManager's update(), render(), postRender(), and cleanUp() methods are internal, users never call them directly.

## Best Practices

You can only change AppStates, or read and write to them, from certain places: In a Control's update() method, in an AppState's update() method, and in the SimpleApplication's simpleUpdate() loop (or the Application's update() loop). To get data from the AppState `MyAppState`:

    app.getState(MyAppState.class).getInfoAboutSomething();

To pass new data into the AppState `MyAppState`:

    app.getState(MyAppState.class).setSomething(blah);

To trigger a one-off method in the AppState `MyAppState`:

    app.getState(MyAppState.class).doSomeMoreStuff();

Don't mess with the AppState from other places, because from other methods you have no control over the order of updates. You don't know when (during which half-finished step of an update), your call was received.

view online version