Sign in to follow this  
Rokkuman

Issues with my statemachine implementation

Recommended Posts

I've written my state machine class based on what I've [i]interpreted[/i] to be the way of doing it, and as a result, I've ended up with a functional state machine system, but the only problem I've come across (so far) is its inability to keep track of unique variables and pointers due to the scope of the State objects. There seems to be several ways of implementing state machines, so I'd like help in creating a "cleaner" version of what I already have now (rather than another system altogether) that also addresses the issues I have with State scope.

What I have is a base state machine class and a base state class. When an entity uses a state machine, a unique Statemachine derivative is created containing variables and entity/actor pointers needed for the entity to behave as intended. The constructor of the derived state machine is responsible for populating itself with its required states. Here is the header for a derived state machine based on what I'm doing now (I don't know if there are official 'exceptions' to defining more than one class within a single header, but I recall seeing it done at least once before and it seems to make more sense to define each state in the header of the state machine than it does to have a separate file for each).

I'd also like insight as to whether or not SM_ should be used as a naming convention for every state machine class I write (As there is also an FPSCamera.h & .cpp in addition to my SM_FPSCamera.h & cpp in my Solution, this seems kind of messy).

[code]

//"SM_FPSCamera.h"

#include "StateMachine.h"
#include "ActorState.h"

#pragma once

class IdleState :
public ActorState
{
public:

IdleState(StateMachine* statemachine, string name) : ActorState(statemachine, name)
{
// Do stuff
}

void StateEnter(Actor* actor)
{
// Do stuff
//Wants to use SM_FPSPlayer::h_camera but can't.
}

void StateUpdate(float timestep, Actor* actor)
{
//Do stuff
//Wants to use SM_FPSPlayer::h_camera but can't.
}
void StateExit(Actor* actor)
{
//Do stuff
//Wants to use SM_FPSPlayer::h_camera but can't.
}

};

class SM_FPSPlayer :
public StateMachine
{
public:
SM_FPSPlayer(void);
~SM_FPSPlayer(void);

Actor* h_camera;
};

[/code]


Please let me know if I wasn't very clear with my problem; I'd be happy to explain more clearly. Thanks a ton in advance.

Share this post


Link to post
Share on other sites
[quote]//Wants to use SM_FPSPlayer::h_camera but can't.[/quote]
Ask yourself why is a camera part of the state machine? Then look at your state machine and ask yourself why you need a new [i]machine[/i] [i]type[/i] for each object.
Your state machine should be a generic object for managing a generic state interface. The machine shouldn't have to know anything about non-state stuff. Your generic state interface should also not care about anything other than the machine it is connected to. But, your derived state classes should care about everything they need. If, in your case, that looks like just an Actor*, then the actor should be the owner of your h_camera handle. So you'd end up with something like:

[code]class IdleState : public ActorState
{
public:
IdleState(StateMachine* statemachine) : ActorState(statemachine, "idle")
{
// Do stuff
}
void Init( Actor *owner )
{
m_owner = owner;
}
void StateEnter()
{
// Do stuff
GetCamera( m_owner->h_camera )->LookAt( m_owner->pos );
}

void StateUpdate(float timestep)
{
//Do stuff
}
void StateExit()
{
//Do stuff
}

private:
Actor *m_owner;
};

//////
class FPSActor : public Actor
{
StateMachine m_machine;
IdleState m_idleState;
FPSActor() : Actor( "fps actor" ), m_idleState( &m_machine )
{
m_idleState.Init( this );
m_machine.AddState( &m_idleState );
m_machine.SetStartState( &m_idleState );
}
}
[/code]

Share this post


Link to post
Share on other sites
Thanks a lot for your reply.
Previously I was making the [i]Actor[/i] the generic class while the statemachine (the "brains") were the unique types, but I can see doing things your way killing more birds with one stone.

I'm unable to test this myself just yet, but just one concern I have with the code you provided. You seem to have an Actor::h_camera when I'd think I probably need an FPSActor::h_camera (despite how it looks, the "camera" entity is something very unique to this entity type and doesn't necessarily behave like a game engine camera; probably wasn't a good example). Let's say I had an entity type DogActor derived from Actor, and I needed IdleState to be able to access DogActor::m_numbones. What changes would be needed to the code you provided to support this, or am I missing something and your code accommodates this just fine?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this