Reputation: 49
I'm setting up a State system for my game.
class State
{
protected:
enum State_
{
STATE_INTRO,
STATE_GAME,
STATE_PAUSE,
STATE_CUTSCENE,
};
public:
State();
virtual void run(State_) = 0;
virtual ~State(); // virtual destructor cus we will be inheriting this class
};
I then have inherited classes which represent each state
class IntroState : public State
{
public:
void run(State_ STATE);
};
I want the run
function to have different functionality based off of what state the game is in, is it bad practice to achieve that like this:
void IntroState::run(State_ STATE)
{
if (STATE == STATE_INTRO)
{
// load the intro
}
}
I'm not sure how else to do this, thanks (and keep in my mind I'm JUST learning about states so I might be completely off here)
Upvotes: 0
Views: 129
Reputation: 530
To expand on my comment, here is a possible approach (improvements are appreciated):
class Game {
//... Initialize all State-derived classes in constructor and put them in states (not shown)
vector<unique_ptr>> states;
State_ currentState {STATE_INTRO};
State_ nextState {STATE_INTRO};
public:
void setNextState(State_ state ) {nextState = state;}
void Play() {
for(;;) { //endless loop
if (!states[currentState]->run()) return;//stopping when run returns false
currentState = nextState;
}
}
};
And run
could look like this:
class IntroState : public State {
//...
void run(Game& game) {
// do stuff
game.setNextState(STATE_GAME);
return true;
}
};
Of course, you need to figure out the include order, and you'll need to forward-declare Game
in State.hpp
(the code shown here only shows the central idea). Also, the implementations of run
and Play
should of course be in seperate .cpp files (didn't do that here so this example wouldn't get too long)
Upvotes: 1
Reputation: 866
I think you don't need polymorphism in your case since you will only have one State
class in your application (correct me if I'm wrong).
You're run function would look like this:
void run(State_ state)
{
switch (state)
{
case STATE_INTRO:
doIntro();
case STATE_BLAH:
doBlah();
// fill all you states...
}
}
void doIntro()
{
// do something for the intro
}
void doBlah()
{
// do something for blah
}
Now if you really wanna get fancy and remove the switch
statement:
class State
{
private:
void doA() {}
void doB() {}
enum State_
{
A = 0,
B,
END_
};
std::function<void(void)> functions[END_];
public:
State()
{
functions[A] = std::bind(&State::doA, this);
functions[B] = std::bind(&State::doB, this);
}
void run(State_ state)
{
functions[state]();
}
};
Upvotes: 1