AppStates/GameStates

I am going to implement AppStates into jME3 soon, and I just want to know, if you guys had any suggestions on how it would be better to do it, since it is such a crucial part of the engine's API. It is going to be very similar to how game states are handled in jME2 with StandardGame.

Momoko_Fan said:

I was strongly considering of forcing AppState usage inside the Application and SimpleApplication


+1

Hi, I am a bit new in the forums, I had no suggestions to make (for now), but I am interested in this post.



What kind of situations AppStates will handle?



I think from examples, anyone could have an idea of what AppStates are and how they should be used :smiley:




If AppStates would be like the jME2 GameStateNodes (which can have also child-gamestates) I would be happy…


ttrocha said:

If AppStates would be like the jME2 GameStateNodes (which can have also child-gamestates) I would be happy...


+1 for me.  I think StandardGame was a step in the right direction but unfortunately its still an after-thought and not completely friendly with the insides of jME2.

I think its important that functionality like using the various render passes with a StandardGame styled design be seamless as it is with BaseGame/SimpleGame.

Is the plan for AppStates to be the defacto way of doing things or will there still be two different systems floating around?  Having such disparity with how things are done between Base/Simple and StandardGame has certainly made for a lot of confused folk around the forums..

I was strongly considering of forcing AppState usage inside the Application and SimpleApplication (where in fact SimpleApplication would itself implement AppState). This way you don't have the mentioned disparity.

I would like to know though, why would you want to use the GameStates as nodes though (via GameStateNode) that essentially means that GameStates work like a high-level scene graph.

I don't really have a need for the parent-child aspect of it, but I can understand in some way why people would want it.  Its basically allowing you to cut out entire chunks of functionality rather than just objects in the visual scene as with the traditional jME scene graph.  I'd be interested in hearing the relational uses people have found for parenting GameStates though…

hmm,…I e.g. used gamestate-parenting for my ingame-hud.  So I have it better seperated from the game-code. Actually that is not strongly needed and maybe I abused a gamestate for that. There are hundrets of ways to achieve the behavior I want so no necessary need for parenting anymore <–


Well with jME3 you will use NiftyGUI now right? Then you just use whatever Nifty provides to do the guis and seperate it from the game or whatever.

I like the game state functionality… +1



just… please, use an instance variable and not a static accessor

I think putting their own tree into each AppState could be the first step towards real concurrency in jme3… When the update(), updateGeometric() and updateLogic() calls of all AppStates are called concurrently on a thread pool this should be a nice and easy way for users to multithread their applications. Of course there are some implications, the trees really have to be separate and should not interact. Maybe add an option for that?

If it is about state machine, I had some experience with this, since in company we're doing j2me development, and almost each such game has a bunch of states and state machines. Often it happened that what we did (using states) worked perfectly except some special situations (you're jumping with the vehicle, bullet hits and kills you in the air -> you're in state_jump and you switch to state_dead… just believe me, wrong state machine design caused a lot of small, annoying issues/bugs). Once my friend found a good solution to state machine implementation in "AI game programming wisdom" book by Steve Rabin. Author presented there very interesting solution for such state machine cause he mentioned that the most common implementation (stateInit(), stateFinalize(), stateUpdate()) may cause some problems. So here is his idea:


  1. We need to have three fields:



private int currentState;
private int newState;
private boolean stateChanged;




2. Then there is a method that handles state transition and each actual state change is done there.


private void processMessage(int message, int param) {
   processState(currentState, message, param);
   int safetyCounter = 0;
   while(stateChanged) {
      processState(currentState, MSG_EXIT, param);
      currentState = newState;
      stateChanged = false;
      processState(currentState, MSG_ENTER, param);
      if(safetyCounter > STATE_SWITCH_SAFETY_COUNTER) {
         throw new RuntimeException("State machine encountered error: there were "+
               safetyCounter+" state switches during one processMessage() call");
      } else {
         safetyCounter += 1;
      }
   }
}



This code handles sending messages to states like: MSG_ENTER (after we switch to state), MSG_EXIT (when we leave state). It also supports situation that after you enter one state, this state might change to another state (while loop takes care of that). And there is a safety counter, cause it may happen that state switching will loop, and if it does, then something is terribly wrong (we enter stateA and immediately switch to stateB and then again to stateC and back to stateA... then stateB... if this happens, we report error).
This method calls processState() method for current state.


3. Create processState(int state, int param) method (example):


private void processState(int state, int message, int param) {
   switch(state) {
      case STATE_INIT:
      {
         switch(message) {
            case MSG_ENTER:
            {
               //Init state.
            }
            break;

            case MSG_UPDATE:
            {
               //Update state.
            }
            break;

            case MSG_EXIT:
            {
               //Finalize state.
            }
            break;
         }
      }
      break;
   }
}




4. Create method for state switching:


private void switchState(int newState) {
   this.stateChanged = true;
   this.newState = newState;
}



WARNING! This method should be called ONLY in processState(...)

Now in some general update you just write:
processMessage(MSG_UPDATE, timeDelta);
and this is how you control states, you send messages to them, and each state handles (or not) particular message. For example, our input handling code sends messages to states, like: processMessage(MSG_LSK, 0);

So that's all. We put such code in many places and it works perfectly. Also this is used in j2me apps, so we use lots of ints, and as few objects as possible, but in desktop application, message can be an object.

Well this is just a solution for state machine, perhaps it might help ;)


Wojtek

AppStates are not a system to track different states of game objects or the scene but a system to have multiple update() loops that can be added/removed from the main loop easily. For example to display a switchable GUI or Menu or another "Level" in a game so they should not interact too much anyway.

What about transitions of game states? I mean things like fading, moving a panel from outside the window, etc (or combinations of those).



That are part of the AppStates API?


arielsan said:

What about transitions of game states? I mean things like fading, moving a panel from outside the window, etc (or combinations of those).

That are part of the AppStates API?

No, you gotta see it more like a callback interface for the physics update() method.

@all Hope people didn't miss my multithreaded proposal over that lengthy post?
normen said:

I think putting their own tree into each AppState could be the first step towards real concurrency in jme3.. When the update(), updateGeometric() and updateLogic() calls of all AppStates are called concurrently on a thread pool this should be a nice and easy way for users to multithread their applications. Of course there are some implications, the trees really have to be separate and should not interact. Maybe add an option for that?

Problem is that logical and geometric updates don't really use that much CPU, unless there are particles or CPU animations, and usually splitting the root node up isn't possible. I think we should multithread only those parts of jME that are CPU intensive and let the rest just run on the "logic" thread.

@woytah: what we are discussing here is "app states" or "passes" that you associate with an application to execute in the main loop.
Momoko_Fan said:

Problem is that logical and geometric updates don't really use that much CPU, unless there are particles or CPU animations, and usually splitting the root node up isn't possible. I think we should multithread only those parts of jME that are CPU intensive and let the rest just run on the "logic" thread.

I thought about the trees being completely separate and the multithreading being an option. You dont know how much CPU the user code in update() munches away.. And having particles on another thread would maybe be nice. Add some sequential callback in AppState before the concurrent update and a world of possibilities opens..
normen said:

Momoko_Fan said:

Problem is that logical and geometric updates don't really use that much CPU, unless there are particles or CPU animations, and usually splitting the root node up isn't possible. I think we should multithread only those parts of jME that are CPU intensive and let the rest just run on the "logic" thread.

I thought about the trees being completely separate and the multithreading being an option. You dont know how much CPU the user code in update() munches away.. And having particles on another thread would maybe be nice. Add some sequential callback in AppState before the concurrent update and a world of possibilities opens..


I'd be inclined to go in the direction that Normen is suggesting.  You never know what someone is going to stick in update(), I think its unrealistic to think that it will just be transformations, particles, animations, etc.

i like that using gamestates it is easy to switch between different parts of your game

for example, "turning on" the pause menu, switching from the login menu to the ingame menu, stuff like that.



the biggest problem i have had with gamestates is that it has disparities with the basegame/simplegame apps, which makes moving code from one to the next sometimes a pain!





but other than that i prefer gamestates for the aforementioned ease of use

Eggsworth said:

the biggest problem i have had with gamestates is that it has disparities with the basegame/simplegame apps, which makes moving code from one to the next sometimes a pain!

This is going to be way better in jme3 as there are not so many prerequisites for stuff like renderstates etc.. Normally there will be only one type of base application. States of course are a horse of a different color as they depend on the main Application rather than replace it.