Это полиморфизм и это плохая практика? - PullRequest
0 голосов
/ 23 апреля 2020

Я настраиваю государственную систему для своей игры.

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
};

Затем я унаследовал классы, которые представляют каждое состояние

class IntroState : public State
{

public:
    void run(State_ STATE);
};

Я хочу, чтобы функция run имела разные функциональные возможности в зависимости от того, в каком состоянии находится игра. плохая практика для достижения этого, как это:

void IntroState::run(State_ STATE)
{
    if (STATE == STATE_INTRO)
    {
        // load the intro
    }
}

Я не уверен, как еще сделать это, спасибо (и имейте в виду, я ПРОСТО узнаю о состояниях, так что я мог бы быть здесь совсем)

Ответы [ 2 ]

1 голос
/ 23 апреля 2020

Чтобы расширить мой комментарий, вот возможный подход (улучшения приветствуются):

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;
      }
    }
};

И run может выглядеть так:

class IntroState : public State {
  //... 
  void run(Game& game) {
    // do stuff
    game.setNextState(STATE_GAME);
    return true;
  }
};

Конечно, вам нужно выяснить порядок включения, и вам нужно будет заранее объявить Game в State.hpp (код, показанный здесь, показывает только центральную идею). Кроме того, реализации run и Play, конечно, должны быть в отдельных. cpp файлах (здесь этого не делали, поэтому этот пример не стал бы слишком длинным)

1 голос
/ 23 апреля 2020

Я думаю, вам не нужен полиморфизм в вашем случае, так как у вас будет только один класс State в вашем приложении (поправьте меня, если я ошибаюсь).

Ваша функция запуска будет выглядеть как это:

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
}

Теперь, если вы действительно хотите получить фантазию и удалить оператор switch:

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]();
        }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...