Using AppStates

Hello guys!



I have started implementing my game using AppStates, but I’m not sure if I’m on the right track.



I have two game states (which will become more in the future). For each game state I have one class that extends AbstractAppState, which contains all the code for that particular game state.



I also have a main class which extends SimpleApplication. In simpleInitApp() I initialize the two AppStates and I attach one of them to the stateManager. Then, in simpleUpdate() I check if the game state has changed and if so, I detach the current AppState and attach the new one.



So, am I doing it right or is there something I should change?

Thanks in advance.

the approach sounds fine to me.

If one state depends on the other then it might be a good idea to do it from the other app state.



Like,



if state 1 is enabled and state 2 is disabled, when state 2 becomes enabled it could, by itself, disable state 1. That way you clean your main’s update loop. That way you don’t have to poll at each and every frame.



Pseudo-code

[java]

public void setEnabled(boolean state) {

if (state) {

enabled = state

app.stateManager().getState(SomeStateClass.class).setEnabled(false);

}

}

[/java]

1 Like

yeh that sounds better :slight_smile:

It is better but only if state 1’s is enabled when state 2 is disabled and vice versa. If both states can be enabled at the same time then the above won’t work obviously.

yh, that meets his requirement, so it should work fine :slight_smile:

Thanks for the responses.



So I should just switch from one game state to another using setEnabled() ?



Also, what about attaching and detaching the states?



If I attach both states, everything appears on the screen at once.



Sorry if the answer I’m looking for is too obvious.

Are your app states also tied to nifty screens? If so it’s also worth thinking about how that’s going to integrate.

Attach both but disable one.



(I actually have in 99% of my app states super.setEnabled(false) in initialize)

In your case @silentsword you should do it the way @zarch proposes.

Thanks a lot for the help, guys. You are great!



I use super.setEnabled(false) in the initialize() method of the AppState, but this only disables the controls. The game objects still appear on the screen. Is there any way to make them not appear as well?



As for the nifty screens, yes, one of the two states currently contains a nifty screen with a picture and some text.

There were no mention of objects…



Where do these come from? What are they? If they’re tied to the app state classes then you’re doing something wrong. Maybe you’re putting them while initializing? If that’s the case then attach those objects to the root node (or the node you’re attaching them) only when the state is enabled. Otherwise, object.detachFromParent() when disabling the state.

Have the app state contain a node. Attach everything related to that app state to the node. In setEnabled() then if enabled is true attach that node to the root node. If false detach it.



(This is why you called super.setEnabled - so you don’t try and remove anything you haven’t added).

If you want your app state to be attached but not “enabled” then you have to not do your initialization on initialize() but do it if enabled is true.



Really, I don’t see a strong benefit in attaching both of them in this case.



I also worry about what you mean by: “In simpleInitApp() I initialize the two AppStates” You know that initialize() is called by state manager and you do not need to call it, right?



If these represent two different stages of your game then just create attach the first one in the beginning and then create and attach the second one, detaching the first, when it’s time.



In general, for an app state that will stay resident you want to adopt a strategy where you have enable() and disable() methods that do the actual adding to and removing from the scene. intialize() is then just for creating any “always resident” stuff and calling enable() if isEnabled() is true. cleanup() is for destroying that “always resident stuff” and calling disable() is isEnabled() is true. setEnabled() then needs to call enable() and disable() as appropriate.



I’ve been meaning to check in a base class that provides this capability because it makes app states way easier to write… but I haven’t thought of a good name for it yet.



Something like this, though:

[java]

public abstract class BaseState extends AbstractAppState {

private String name;

private AppStateManager stateManager;

private Application app;



protected BaseState( String name, boolean enabled ) {

super.setEnabled(enabled);

this.name = name;

}



public final String getName() {

return name;

}



@Override

public final void initialize( AppStateManager stateManager, Application app ) {

super.initialize( stateManager, app );



this.stateManager = stateManager;

this.app = app;

initialize( app );

if( isEnabled() )

enable();

}



@Override

public final void cleanup() {

if( isEnabled() )

disable();

super.cleanup();

this.stateManager = null;

}



protected final Application getApplication() {

return app;

}



protected final AppStateManager getStateManager() {

return stateManager;

}



protected final <T extends AppState> T getState( Class<T> type ) {

return stateManager.getState(type);

}



public final void setEnabled( boolean enabled ) {

if( isEnabled() == enabled )

return;



super.setEnabled(enabled);



if( enabled && stateManager != null )

enable();

else if( !enabled && stateManager != null )

disable();

}



protected abstract void initializeState( Application app );



protected abstract void cleanupState( Application app );



protected abstract void enable();



protected abstract void disable();



public String toString() {

return getClass().getSimpleName() + “[” + name + “]”;

}

}

[/java]



Which is a stripped down version of the base app state class that I use… I left the “name” stuff in because I find it useful when debugging. I also may have stripped it down badly and gotten something wrong… but it’s the general gist.