SSSF --> SnowStorm State Framework

Anything and everything that's related to OGRE or the wider graphics field that doesn't fit into the other forums.
User avatar
Walley
Greenskin
Posts: 120
Joined: Fri Dec 03, 2004 4:37 am
Location: Victoria, Australia

.

Post by Walley »

In regards to buffered input and unbuffered input, I'm using a heavily modified version of Robo's state framework, which provides for both, basically allowing you to have either buffered or unbuffered, or both.
Of late I've been giving it all a good test, design wise, in my current side project, and I'm working on finishing off the implemention of a state heirarchy (ie. states can have children and parents).
These additions make the State class somewhat more complex, and there are also additions/modifications to StateEngine and StateHandler. I'll post some code up tonight, as I should have finished off the heirarchy stuff by the time I'm home.
eeheeehe
Gnoblar
Posts: 22
Joined: Sun Mar 20, 2005 9:46 pm

Post by eeheeehe »

I get this error when trying to change states from within another state:

Code: Select all

States/GS_Intro.cpp: In member function `virtual bool 
   States::GS_Intro::OnKeyEvent(float)':
States/GS_Intro.cpp:54: error: cannot call member function `virtual bool 
   SSSF::Game_State_Handler::ChangeState(std::basic_string<char, 

   std::char_traits<char>, std::allocator<char> >)' without object
Does anyone know how to fix this?
Whitebear
Greenskin
Posts: 147
Joined: Mon Oct 25, 2004 5:22 am
Location: RF
x 1

Post by Whitebear »

How do you call the method ChangeState()? It's not a static one and thus requires an instance of GameStateHandler object.
\_ :roll:_/
User avatar
Walley
Greenskin
Posts: 120
Joined: Fri Dec 03, 2004 4:37 am
Location: Victoria, Australia

Post by Walley »

Either pass around a pointer to the handler, or use a singleton.
User avatar
Robomaniac
Hobgoblin
Posts: 508
Joined: Tue Feb 03, 2004 6:39 am

Post by Robomaniac »

In my system (as you can probably see by the GS_SinglePlayer class), i pass around a GameEngine* m_Creator; You can use this to access the ChangeState function, which you pass a std::string of the class name (again, registered via GameStateHandler::addState(std::string name, GameState* state);

Another Note, in order to use ogre with the GSM you need to include the folder ../Graphics also as it contains all the grapical stuff you need (initialization, singleton stuff, etc)

[edit]
If y'all poke me enough, I'll make a tutorial/specialized GSM release this weekend (yay, get to sleep at home :))
phear hingo

My Webpage
User avatar
Walley
Greenskin
Posts: 120
Joined: Fri Dec 03, 2004 4:37 am
Location: Victoria, Australia

Post by Walley »

Well I'll add my two cents and post my version of the framework - perhaps you'll find something you like and add it to yours or some such.

http://gd.notafront.org/walley/OgreStateFramework.rar

Now I've taken the approach of having the state engine as a singleton, although this is in some ways a bad design decision, I'll most likely refactor it out sometime soon.
Oh, secondly, I haven't included any example states, but seeing as I don't have State as abstract (although it's almost useless on it's own, although it can still be used as a parent state. It's not much effort to change this of course, so let me know what you think), you can muck around with State itself when testing.

Anyway, here's some example code:

Code: Select all

// The state engine uses some defined constants for default file path
// initialization, such as the logging file path.
#include "Defines.h"

#include "State Framework\StateEngine.h"

int main() {
    // Note that the actual namespace name is StateFramework, but
    // StateF is available as well for 'short hand'
    StateF::StateEngine* engine = new StateF::StateEngine();

    // Initialize the state engine with the defaults
    // Be sure to look at the initialization methods for a better idea
    // Here we're specifying a default of 5 mipmaps, and to have both
    // buffered and unbuffered input for the active states
    engine->Initialize(5, StateF::IM_BUFFERED_AND_UNBUFFERED);

    // Add test state
    engine->AddState(new StateF::State("Test State"));

    // Add a child to the test state
    // Note that state->ActivateChild(childName) must be called before
    // the child state will be updated, usually this should be done from
    // within the parent state. Additionally, children should usually be
    // added from within the parent state, but this is just an example.
    engine->GetState("Test State")->AddChild(new StateF::State("Test Child State");
    engine->GetState("Test State")->ActivateChild("Test Child State");

    // A big difference here is the return types.
    // Here, Update returns an integer, where the StateF::StateReturn
    // enum is for the purpose of determining the type.
    engine->SetState("Test State");

    int stateReturn = StateF::SR_TRUE;
    while (stateReturn == StateF::SR_TRUE) {
        stateReturn = engine->Update();
    }

    // Quit if necessary
    // SR_QUIT is for the purpose of allowing states to specify that
    // program execution should end, whereas SR_FALSE is generally
    // for specifying that the next state should be set.
    if (stateReturn == StateF::SR_QUIT)
        ... // Shutdown, quit, etc

    delete engine; // Note that the destructor automatically calls Destroy

    return 0;
}
And, without comments:

Code: Select all

#include "Defines.h"

#include "State Framework\StateEngine.h"

int main() {
    StateF::StateEngine* engine = new StateF::StateEngine();
    engine->Initialize(5, StateF::IM_BUFFERED_AND_UNBUFFERED);

    engine->AddState(new StateF::State("Test State"));
    engine->GetState("Test State")->AddChild(new StateF::State("Test Child State");
    engine->GetState("Test State")->ActivateChild("Test Child State");

    engine->SetState("Test State");

    int stateReturn = StateF::SR_TRUE;
    while (stateReturn == StateF::SR_TRUE) {
        stateReturn = engine->Update();
    }

    if (stateReturn == StateF::SR_QUIT)
        ... // Shutdown, quit, etc

    delete engine;

    return 0;
}
To get a feel for it you're best to dig through the source, I can't really be bothered providing any form of documentation considering I've not had a chance to fully test it, both for current functionality, and for design applicability (ie. what features does it still need, is there anything wrong with the interface for the current features).
Also note that the code is currently windows specific (ie. it includes windows.h), although it wouldn't take much to remove these (in fact I don't think they're even needed, but I'll check that later).
Last edited by Walley on Thu May 05, 2005 1:26 am, edited 1 time in total.
eeheeehe
Gnoblar
Posts: 22
Joined: Sun Mar 20, 2005 9:46 pm

w00t!

Post by eeheeehe »

Well... now that I am fully awake, and I looked @ the code, it turns out that there is a m_Engine pointer that I can use to make the change state work. Made a big deal out of a little problem. Thanks for the help guys! The help tipped me off to look where I didn't at first.
User avatar
Robomaniac
Hobgoblin
Posts: 508
Joined: Tue Feb 03, 2004 6:39 am

Post by Robomaniac »

Glad to hear.

I'll create a separate source .zip for the GSM, and write a small readme file to it :)

Someone in irc remind me to do so on saturday
phear hingo

My Webpage
eeheeehe
Gnoblar
Posts: 22
Joined: Sun Mar 20, 2005 9:46 pm

Post by eeheeehe »

There seems to be a problem when trying to load a texture. I get this error that says that the texture cannot be found.
User avatar
Walley
Greenskin
Posts: 120
Joined: Fri Dec 03, 2004 4:37 am
Location: Victoria, Australia

Post by Walley »

That's not specific to the framework and hence shouldn't be asked here. It would be related to using Ogre properly...
eeheeehe
Gnoblar
Posts: 22
Joined: Sun Mar 20, 2005 9:46 pm

Post by eeheeehe »

Okay, I fixed that problem. But now (Surprise) I have another question... With the modified state changer, would I have to hide everything on in a state individually, or could I hide the whole state at once?
User avatar
Robomaniac
Hobgoblin
Posts: 508
Joined: Tue Feb 03, 2004 6:39 am

Post by Robomaniac »

I will post a release of sssf tonight probably, i want to add the ability to have substates in each state first (ex, a Menu game state contains the Option_Menu substate, Game game state contains the Select Kit substate, etc)

Shouldn't take more then 15 minutes
phear hingo

My Webpage
User avatar
Robomaniac
Hobgoblin
Posts: 508
Joined: Tue Feb 03, 2004 6:39 am

Post by Robomaniac »

http://centaurforce.sf.net/SSSF.rar

No project included, just add it to your current project, add the ogre headers to your include path, and link to the lib, should work fine.

The hierarchy capabilities of game states is yet untested, but it should work similar to the way that regular states are used, except that the GameState class manages them instead of the GameStateHandler

Code: Select all

GameStateHandler* gsh = new GameStateHandler();
GameState* gs = new GameState_smthg(gsh);

gsh->addState("smthg", gs);

GameState* gs2 = new GameState_SmthgChild(gsh, gs);
gs->addChildState(gs2, "SmthgChild");

gs->setActiveChild("SmthgChild");
NB: THAT IS PSEUDO CODE, DO NOT COPY/PASTE THAT CODE.

If you have any problems, feel free to contact me :)
phear hingo

My Webpage
Tyn
Gremlin
Posts: 195
Joined: Mon Jul 19, 2004 11:40 pm
Location: England
Contact:

Post by Tyn »

Hey

We've decided to mod the singleton version of this framework that Walley provided after scanning through the frameworks for Ogre that are around.

Firstly, thanks to Robo for the original code and Walley for his mods, it seems to serve well with what we need from a game engine and after we arrange it to suit ourselves we will call the result Meta, which will be talored for specific use in 2080. Thanks, the design seems solid and will allow us to cater for our specific needs.

Secondly, to address the guy who was having trouble changing states. One modification we made was to queue up state changes until the end of the main update loop. After tracing it back with the debugger it will crash if you try to change the current state half way through this loop.

HTH, and thanks again for all contributers to the code.
"A common mistake that people make when trying to design something completely foolproof is to underestimate the ingenuity of complete fools."
Douglas Adams

http://www.spacecolonization.net
2080: Space Colonization
User avatar
Walley
Greenskin
Posts: 120
Joined: Fri Dec 03, 2004 4:37 am
Location: Victoria, Australia

.

Post by Walley »

Let it be noted that I shouldn't have made the StateEngine a singleton - that's a design flaw. Whilst they are convenient, the system should be more centralized, as singletons are something which should only be used sparingly.

Anyway, nice to know I've been of some help, but even now I look down on some of the things in that version of the StateEngine I posted, so don't be too satisfied with it!
Tyn
Gremlin
Posts: 195
Joined: Mon Jul 19, 2004 11:40 pm
Location: England
Contact:

Post by Tyn »

Oh, don't worry, I haven't just plonked the code in there never to be touched again, I'm quite active in changing it to suit the design I'm after, there's some stuff there which needed to be added and some stuff which I don't use. It was a nice start tho, thanks.

I'm quite interested that you think making the main engine class a singleton is a bad idea, so far it seems to make changing state a lot less complex, one function that can be accessed anywhere to change the state. In terms of clean code, it seems the best option, is there something else I should be considering?

Cheers.
"A common mistake that people make when trying to design something completely foolproof is to underestimate the ingenuity of complete fools."
Douglas Adams

http://www.spacecolonization.net
2080: Space Colonization
User avatar
Walley
Greenskin
Posts: 120
Joined: Fri Dec 03, 2004 4:37 am
Location: Victoria, Australia

Post by Walley »

Hmm. I'm never that great at explaining things, so I'll refer you to the journal of Washu.
http://www.gamedev.net/community/forums ... user=Washu
Look at the entries for April 21-25, on singletonitis.
The general reason here is that pretty much nothing but states and the main function require access to the state system, so a pointer should be passed down to states. Secondly, singletons are essentially over-glorified globals, and nobody likes globals :).
Post Reply