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.

To implement game logic:

  1. You define a custom AppState and implement its behaviour in the AppState's update() method.
    • You can pass arguments and manipulate everything inside the app's scope.
  2. Attach the AppState to your application's AppStateManager (stateManager.attach(myAppState);) to activate it.
  3. Create one AppState for each type of game behavior. When you add several AppStates to one Application, they will be executed in the order they were added.

Usage 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:

AppState

The AppState interface allows you to hook a continously executing piece of code into the main loop.

AppState MethodUsage
isActive()Test whether AppState is enabled or disabled.
stateAttached(asm)
stateDetached(asm)
The AppState knows when it is attached to, or detached from, the AppStateManager. Then it triggers these methods that you implement.
isInitialized()Your implementations of this interface should return the correct respective boolean value.
initialize(asm,app)The RenderThread initialized the AppState and then calls this method.
setActive(true)
setActive(false)
Temporarily enables or disables an AppState.
update(float tpf)Here you implement the behaviour that you want to hook into the main update loop.
cleanup()Called when when the AppState is de-initialized.
render(RenderManager rm)Renders the state.
postRender()Called after all rendering commands are flushed.

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
 
    public Node getX(){
        return x;
    }
 
    @Override
    public void update(float tpf) {
        x.doSomething();             // implement behaviour
    }
}

Usage:

public class TestAppStates extends Application {
  public static void main(String[] args){
    TestAppStates app = new TestAppStates();
    app.start();
  }
 
  @Override
  public void initialize(){
    super.initialize();
    MyAppState state = new MyAppState();
    stateManager.attach(state);
    System.out.println("Use the state's methods... " + state.getX());
  }
 
  @Override
  public void update(){
    super.update();
    stateManager.update(tpf);
    stateManager.render(renderManager);
    renderManager.render(tpf);
  }
}

Note: If you use the AppState together with a SimpleApplication-based class, then this update() loop is already set up.

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 MethodUsage
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 it 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