(C++) Dynamically managing states of the game entity

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
TheWorstCoderEver
Posts: 47
Joined: Wed Feb 01, 2006 8:09 pm
Location: Wroclaw
Contact:

(C++) Dynamically managing states of the game entity

Post by TheWorstCoderEver »

Looking at the code of my basic game entity ("How to move and animate an entity" snippet) I realised it would be best to describe entity with dynamically created, rather than pre-defined, states - for the sake of flexibility. This is how I came up with the system that I'm going to describe.

First step was to define the state itself. I originally wanted it to be a structure, but later on decided it will be easier to manipulate the state if will be defined as a class. Reasoning along these lines, I created the following definition:

Code: Select all


class State
{
    private:

    const char* name;
    int value;
    bool enabled;

    public:

    State(const char* Name)
    {
        this->name=Name;
    }
    ~State()
    {
    }
    void Enable()
    {
        this->enabled=true;
    }
    void Disable()
    {
        this->enabled=false;
    }
    void Set(int Value)
    {
        this->value=Value;
    }

    const char* GetName()
    {
        return this->name;
    }

    int GetValue()
    {
        return this->value;
    }
    bool IsEnabled()
    {
        return this->enabled;
    }
};

The definition's pretty straightforward, and most of the implementation is inline. The State class object has three properties - name, numeric value and boolean value, all of which can be accessed via its public methods. Name property is used for identification. My next step was to create a member property for the game object that would store its states:

Code: Select all

 std::list<State*> CurrentStates; 
The States are then created, appended, looked up and manipulated via following member methods of the game object:

Code: Select all


void Character::AppendState(const char* name)
{
    State* stat = new State(name);
    stat->Disable();
    stat->Set(0);
    CurrentStates.push_back(stat);
}

State* Character::QueryState(const char* name)
{

      std::list<State*>::iterator i;
      for(i=CurrentStates.begin();i!=CurrentStates.end();i++)
      {
          if((*i)->GetName()==name) return (*i);
      }
      return NULL;
}

First method creates a new State type object and places it on the list. The latter looks up the state, taking its name as the argument, and - depending on whether the operation is succesful or not - returns either the pointer to State type object or a NULL pointer. Once the state is found by the QueryState method, it can be easily manipulated via its member methods:

Code: Select all

 

void Character::WalkAndStop()
{
    if(QueryState("isMoving")->IsEnabled())
    {
        //turn on the walking animation
    }


That's all to it. The code was written in Code::Blocks, and tested in the application compiled with MinGW. I hope it will prove useful for the Irrlicht forum users.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Did you really test this, or did you just write it up? It should compile, but will never work. Your char* handling is completely wrong. First, only the temporary pointer is stored (unless you always create states with strdup("statename")) and the comparison at the end is also just comparing pointers which will never yield true.
And I think that game states should be handled just like automata or state machines which does not really fit your layout.
Oh, could you please delete the other post?
TheWorstCoderEver
Posts: 47
Joined: Wed Feb 01, 2006 8:09 pm
Location: Wroclaw
Contact:

Post by TheWorstCoderEver »

My amateurishness finally became apparent.

Yes, I have tested the code in my Crystal Space application. It tests whether the entity's "isWalking" state is enabled, and - if it's not - stops the walking animation. When the player moves the character onwards, "isMoving" property is enabled again, and the animation is resumed (as a result of enabling the property). So yes, the code's working.

Perhaps this concept is closer to property rather than state. I came up with it because - frankly - I've had limited (if any) knowledge of the finite state machines at the time. If you think that this newbie post of mine does nothing but hinders other newbies (which I admit might indeed be the case), I'll apply to moderators to remove it from the forum.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

So I still have my doubts that this code is ok. But anyway I'd suggest to use maps or even better hash maps to store properties. If you just need boolean properties you can simply check for existence of the string. Should be much faster than linear search. And for a fixed set of properties it's even better to use an enum and a boolean array.
stodge
Posts: 216
Joined: Fri Dec 05, 2003 5:57 pm

Post by stodge »

I don't have a problem with code that doesn't compile if you're just explaining a design idea.

Use an std::map instead of a list, then you can do this:

Code: Select all

State* Character::QueryState(const char* name) 
{ 

      return CurrentStates[name];
} 
Or something similar.... If you're doing a lookup on a name, a list is pointless due to the searching. For example:

http://habitat3d.cvs.sourceforge.net/ha ... iew=markup
Post Reply