Program states...

Started by
4 comments, last by Noods 15 years, 5 months ago
I am coming to the point in my Win32 program where I have the need for different program states. In these states, different controls will be active and the input will be handled differently between the states. Obviously I will need to change the way my main WinProc handles messages. What are some methods for dealing with this? Is there a way to have more then one WinProc? Should I just add state checks to handle this? How do programs with many different states handle this? Thanks! -Noods
Advertisement
Im not the best with win32, and as such I dont know if there is a function to change the winproc a window is using, but if there is, having multiple functions might be the ticket.

If not, a switch statement would probably work. Its not quite the same, but the NPCs I have all use one function, Update, that gets called each frame, and in it is a switch, with different actions for each state. Basically all of my AI is just a switch for the NPCs state, wander, advance, attack, etc.
You probably can change the WndProc, but whether you should is another question.

It would probably be better to handle state in another place which is unaware of WndProc or other Windows bootstrapping code.

The simplest way would be to have a switch statement on the current state in your Update/Render/Input methods:

void Update(){   switch(_currentState)   {      case GameState.Menu:         UpdateMenuTitle();         break;      case GameState.InGame:         UpdateObjects();         UpdateHUD();         break;   }}


A more involved architecture would use the state pattern, encapsulating a state in an object:

void Update(){   _currentState.Update();}class MenuState : IGameState{   public void Update()   {      _menu.Update();   }}class InGameState : IGameState{   public void Update()   {      _objectManager.Update();      _hud.Update();   }}


Also, look up Finite State Machine in [google] - here at gamedev there are articles on FSMs.
You can change the WndProc like this:

SetLastError( NO_ERROR );SetWindowLongPtr( hwnd, GWLP_WNDPROC, (LONG_PTR) NewWndProc );if( GetLastError() != NO_ERROR )  throw something;
I wouldn't change the WndProc directly like that... you're highly likely to lose track of which one you should be in at some point, which is either going to manifest in some really odd-seeming behavior, or crash the application because it tries to access something that exists in the state it believes itself to be in, but doesn't in the state its really in.

Furthermore, there are quite a few messages which will likely always be handled in the same way, which would have to be duplicated and maintained across each WndProc (Thisngs like window move/resize or screensaver messages, for instance). Its far more stable to just have a single WndProc, which handles common messages, and which dispatches other messages of interest to each gamestate to be handled -- this mirrors the fact that the difference lies in how the message is interpreted between states, not how the application should respond to messages.

This fits nicely into the state pattern, which should define an interface which accepts these types of messages and provide any supporting functionality needed by the common messages.

I also like to go further by employing a static WndProc which dispatches messages based on class-member handlers that have been registered with the WndProc. This allows great flexibility, and facilitates the WndProc to be encapsulated within a reusable class.


If you'd like to see these techniques in real code, you can download my Windows Mobile Game Starter Kit featuring SkiTime mobile from MSDN. While the code is targeted against Windows Mobile, and the solution file won't do you any good unless you're set up for Windows Mobile development, you can read the code and learn a lot. I use this Windows base code at home nearly unmodified to develop Desktop applications. Its also clean, concise and extremely well commented, if I do say so myself.

throw table_exception("(? ???)? ? ???");

The state pattern seems like a pretty good solution to what I am looking for. However, I have not used it in the past and this is really my first time coming across it. Is it typically implemented with inherited code where the input processing is the same and overrides where the input processing is different?

This topic is closed to new replies.

Advertisement