Click here to Skip to main content
15,889,595 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
My project includes a BaseEntity class which does basic stuff like drawing an object on the screen. I have a subclass of BaseEntity called Seeker which makes a BaseEntity object go to a specific place (through a function which is called each frame). I have a subclass of BaseEntity called Flee which does the opposite. What I want to do is create a BaseEntity object which will act like a seeker on initialization and after reaching the destination I want to change its behaviour and act like a Fleer for a short time and then back to seeking. I was thinking about creating a Finite State Machine
C++
  class state:public BaseEntity
{
public:
    virtual void onenter() = 0;
    virtual void update() = 0;
    virtual void onexit() = 0;
};


class seek : public state
{
public:
    void onenter() override;
    void update() override;
    void onexit() override;
};

class flee : public state
{
public:
    void onenter() override;
    void update() override;
    void onexit() override;
};

I am not sure how create my "player", where to put the piece of code which moves the player, how to make the tranzition between states, how to make make player2 aware of player1 state( once player1 reaches destination, player2 starts seeking and vice versa). My game will be pretty simple, only 2 states, which means I don't have to make it fully encapsulated or worry about 2 states running at the same time. I was thinking about using an enum/switch approach but I would like to do stuff while entering a state( like giving the player a specific colour to know what is he doing or just print a message), another problem is that I need to run onenter and onexit functions only once and I need to run update in a while(true){}

What I have tried:

I tried to implement a class for each behaviour, but I don't know how to link that class with a BaseEntity object
Posted
Updated 5-Jan-20 23:26pm

Maybe this CodeProject question will help: State Machine Design in C++[^]
 
Share this answer
 
You do not need a switch-case statement when you have class methods available to you. For each variable you might switch on, declare a virtual method that implements that functionality and call it. Then it is a matter to define objects with the appropriate methods.

When I have done this kind of thing, I found the state class needs a pointer to its containing object and, of course, the object needs an instance of the state class which is usually through a pointer. You can implement OnEnterState and OnExitState methods to do what their names imply. To change states or functions, you destroy one state object, construct the new one, and inform the object it has a new state.

Every time you are tempted to use a switch-case statement consider making a virtual method that will eliminate the decision for you. In other words, if you are about to make a switch statement that does an action based on the state, make a virtual method for the state class that has specialized implementations for each state along with a default implementation that does the common functionality or nothing at all, as needed.
 
Share this answer
 
Your classes describe the state machine without if or switch, and that's fine. You need to add virtual destructors though! Now you only need to add one state (the starting state) to each player and some events that trigger a change of state:
C++
class player {
   std::unique_ptr<state> current_state;
public:
   player(std::unique_ptr<state> starting_state) : current_state(starting_state) {}
   void setState(std::unique_ptr<state> other_state) { current_state = other_state; }
   void onSwitch() { /* switch to other state */ }
   void onFlee() { current_state = new flee; }
   void onSeek() { current_state = new seek; }
};

Then you need to insert code that describes the interaction between players. Maybe a class arena that contains the players and controls when and how they (inter)act:
C++
class arena {
   player player1;
   player player2;
   int player1_score;
   int player2_score;
public:
   arena() : player1(new seek()), player2(new flee()) {}
   void startGame (); // starts a new game
   void nextTurn(); // generates (random) event(s) for the players
   int currentLeader(); // returns the player who is currently leading the scoreboard
};
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900