This topic is 3667 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Since I started work, we've been using state machines everywhere to work with the different states of objects (as you would expect :D). Previously, I had been doing it the harder way, by creating an enum that lists the different states, having a member variable describing the current state and just having a large 'if else' in the object's update function. I decided to write one last night for my current demo, which is still in fairly early stages, so there was practically no changes necessary. each state is a single object with 3 functions: onEnter, onExit, onUpdate. Now, even the first thing I needed to do was to have a state for a particular game object and I had to write a base object for that state and then another object for each state.
class StateMachineState
{
public:

virtual void onEnter() = 0;
virtual void onUpdate() = 0;
virtual void onExit() = 0;

};

class ObjectStateMachineState	:	public StateMachineState
{
private:
Object* ptr;

public:

ObjectStateMachineState(Object* p)
:	ptr(p)
{ }
};


And then I derive the needed classes, like 'move', etc, etc from 'ObjectStateMachineState'. The problem with this is that with simple states, like the one I implemented last night, which is nothing more than moving an object according to the current frame's timestep, still took 20 or so lines, apart from the one line creation and another to change the state. For a complicated class, this is no problem as complex classes are often longer and so 20 lines seems like very little, but with a class whose required functionality is two lines, having to write a 20 line class seems a bit much. Is it too much? Is it worth it leaving my states as individual objects?

##### Share on other sites
I'd just use an enum with switch statements. Using inheritance for this seems unnecessary.

Can you give an example of a FSM that you are trying to implement?

##### Share on other sites
Quote:
 Original post by PoitaI'd just use an enum with switch statements. Using inheritance for this seems unnecessary.Can you give an example of a FSM that you are trying to implement?

Yes, inheritance for this particular FSM is unnecessary, at least at the moment. I do intend to do some basic AI soon and I thought that a state machine would be useful.

In the state stuff I've done previously, I did use an enum with switch statement, but I found it ... well, iffy in terms of easily finding the enter and exit code, not to mention that the update function was usually a large, messy function.

##### Share on other sites
It seems to me that you're not usually going to write states like Move. Instead you'll probably use states like Chase, Evade, Patrol, etc, and those will most likely not take 2 (or 20) lines of code. With these you might see more benefit.

##### Share on other sites
Do you think it would be easier to have an enum and an 'if else' in the object update function, for the simpler things like 'move', 'turn' and the simpler states, or should I just leave it as it is and use the state machine and state objects for everything to prevent confusion?

I would still use the state machine for the higher level AI states such as Chase, Evade, etc to make the descisions, regardless of whether I go the enum way for the simpler states.

##### Share on other sites
leave your state's as individual objects. You can always use some macros to reduce the code required for 2 line states. It's easy to implement, easy to read and understand, and easy to debug. In the long run, trust me, it's a very good idea.... (speaking from experiance)

##### Share on other sites
rob can you give an example of the macros you might use?

can it be templated?

##### Share on other sites
A really basic macro for declaring a base class state for an object

#define DECLARE_BASE_STATE(X)   class X##StateMachineState : public StateMachineState {   public:     X##StateMachineState(X* obj) : mObject(obj) {}   protected:     X* mObject;   };

then to replace the OP's original example, you'd just need to do :

DECLARE_BASE_STATE(Object)

Then extend with something like:

#define DECLARE_MOVE_FORWARD(X)   class X##MoveForwardState : public X##StateMachineState {   public:     X##MoveForwardState(X* obj) : X##StateMachineState(obj) {}     void onUpdate() {       mObject->Position += mObject->GetForwardDir()*GetTimeStep();     }   }; #define DECLARE_MOVE_BACKWARD(X)   class X##MoveBackwardState : public X##StateMachineState {   public:     X##MoveBackwardState(X* obj) : X##StateMachineState(obj) {}     void onUpdate() {       mObject->Position -= mObject->GetForwardDir()*GetTimeStep();     }   }; #define DECLARE_MOVE_FORWARD_BACKWARD(X)    DECLARE_MOVE_FORWARD(X)    DECLARE_MOVE_BACKWARD(X)

Yes, you could use a template such as:

  template<typename T>  class TStateMachineState     : public StateMachineState {   public:     TStateMachineState(T* obj)       : mObject(obj) {}   protected:     T* mObject;   };  template<typename T>  class TForwardStateMachineState     : public TStateMachineState<T> {   public:     void onUpdate() {      mObject->Position += mObject->GetForwardDir()*GetTimeStep();    }  };  template<typename T>  class TBackwardStateMachineState     : public TStateMachineState<T> {   public:     void onUpdate() {      mObject->Position -= mObject->GetForwardDir()*GetTimeStep();    }  };

personally speaking, I prefer the macro approach. - I'm now expecting someone to list the reasons as to why templates are better than macros. I'm not wanting to get into a religous war over it, so save yourself the effort ;)

##### Share on other sites
sorry, the source tags remove the \'s from the macros.... tried duplicated without any formatting, but neither the source, code, pre tags, or untagged text allows you to use \'s.

##### Share on other sites
If the little states follow a particular pattern then it might be sufficient to template them. If the little states are almost similar except for Update (for example) then it might be sufficient to make a common 'simple' state that takes a function object strategy for the very little difference.

But frankly, if you 'waste' 18 lines for a few little states but save a few dozen hours of developer time in modularity, readability and maintainability that's huge gain. Don't miss the forest for the trees.

##### Share on other sites
Quote:
 Original post by EndarFor a complicated class, this is no problem as complex classes are often longer and so 20 lines seems like very little, but with a class whose required functionality is two lines, having to write a 20 line class seems a bit much.Is it too much? Is it worth it leaving my states as individual objects?

Forgive me for writing Python in C++ syntax, but I'd probably adopt something like this:
template<typename Object, typename Callable>class StateMachineState{public:    StateMachineState(Object obj, Callable onEnter, Callable onUpdate, Callable onExit);private:    Object object;    Callable onEnter;    Callable onUpdate;    Callable onExit;public:    void enter()  { onEnter(object); }    void update() { onUpdate(object); }    void exit()   { onExit(object); }};

No inheritance, just pass in function objects for the stuff you want called. Boost::bind or something similar will clean up member functions if you need them.

##### Share on other sites
I wrote a state machine system very similar to this. When I was implementing game logic in C++, it was a pain to write all the extra code, but when I moved the state code to Lua, it became obvious that this implementation was better than a big switch statement.

##### Share on other sites
Quote:
 Is it too much? Is it worth it leaving my states as individual objects?

10 Reasons the Age of
Finite State Machines is Over

That would make for some interesting discussion(s)
(if you want to bleed at the edge ...so to speak)

I guess you have no choice at work ... but you do have a choice in your demo
to experiment/test out the merits of the claims of the article...and possibly earn some browny points.

We had to start somewhere with AI (and stuff), and FSM has long been
an important concept (comp. science 101 type stuff?). I've sort of viewed FSM concepts as already implied in
much programming anyhow (as has been the typical programmer's perogative to abuse the FSM concept?). But being so openly explicit about it with a StateMachineState class seems a bit too much: It's more to do with feeling (ewwwh... I mean holistic approach..) than with logical reasoning (I would have to concentrate too hard to give logical reasons; there it is again...my open ignorance!)

Anyhow... hope you find the link interesting .. I do..but it doesn't look like a particularly "better" alternative ( ...being up to the reader to decide).

[Edited by - steven katic on January 2, 2008 4:03:48 PM]

##### Share on other sites

This topic is 3667 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.