2017-05-24 19 views
0

私の質問は: 私は自分のプロジェクトで基本的な状態管理を実装しようとしています。 私はstd::stack<State*>コンテナにすべての状態を持ち、アプリケーションクラスまたは状態クラスから直接プッシュ/ポップします。 問題は、現在の状態をStateクラスから変更すると、レンダリングメソッドが呼び出される前に破棄される可能性があります。だから私はこれを避けるのですか? 私の英語のためのPS申し訳ありませんが、私の問題/コードで何かが明確C++の実装状態

ApplicationクラスにISNなら、私に言ってください。

void Application::pushState(State* state) 
{ 
    this->m_states.push(state); 
    this->m_states.top()->open();//enter state 
} 

void Application::popState() 
{ 
    if (!this->m_states.empty()) 
    { 
     this->m_states.top()->close();//leave state 
     delete this->m_states.top(); 
    } 

    if (!this->m_states.empty()) 
    this->m_states.pop(); 
} 

void Application::changeState(State* state) 
{ 
    if (!this->m_states.empty()) 
     popState(); 
    pushState(state); 
} 

State* Application::peekState() 
{ 
    if (this->m_states.empty()) return nullptr; 
    return this->m_states.top(); 
} 

void Application::mainLoop() 
{ 
    sf::Clock clock; 

    while (this->m_window.isOpen()) 
    { 
     sf::Time elapsed = clock.restart(); 
     float delta = elapsed.asSeconds(); 

     if (this->peekState() == nullptr) 
      this->m_window.close(); 
     this->peekState()->update(delta)//if i change state in State.update(), it may be that code below will now point to not existing state 

     if (this->peekState() == nullptr) 
      this->m_window.close(); 
     this->peekState()->render(delta); 
    } 
} 

Stateクラス:

void EditorState::update(const float delta) 
{ 
    sf::Event event; 
    while (this->m_application->m_window.pollEvent(event)) 
    { 
     if (event.type == sf::Event::Closed) 
     { 
      this->m_application->popState(); 
      return; 
     } 
    } 
} 

さて、多分これは本当にではありません問題は、しかし、 "どのように"質問するようなものです。私のコードで見ることができるように、mainLoop()メソッドで状態を更新してレンダリングします。どのように把握するかは、stateManager(私の場合はアプリケーションクラス)からだけでなく、state自体も状態を変更することができるように、これらの更新を管理する方法です。

+0

ようこそスタックオーバーフロー。 [The Tour](http://stackoverflow.com/tour)を読み、[ヘルプセンター](http://stackoverflow.com/help/asking)の資料を参考にしてください。ここに聞いてください。 –

+2

スタックを状態を保持するための正しいデータ構造にしてもよろしいですか? [this](http://makulik.github.io/sttcl/)に興味があるかもしれません。 –

+0

確かに、おそらく私はベクトルに変更することができますが、全体的にこれは私の問題とは思わない – joe503

答えて

1

これはゲーム用です(ただし、必ずしもそうである必要はありません)。状態を切り替えるためにあなたがやっていることをする代わりに、私は列挙型を使います。

enum class GameState { 
    MENU, PLAY, PAUSE 
} 

その後、メインループでは、あなたのメインヘッダ

GameState m_gameState = GameState::MENU; 

に、あなたは単に

if (m_gameState == GameState::MENU) 
{ 
    ... 
} 

を行うことにより、現在の状態が何であるかを確認することができます。または、switchステートメントを使用することができます

switch (m_gameState) 
{ 
case GameState::MENU: 
    ... 
    break; 
case GameState::PLAY: 
    ... 
    break; 
case GameState::PAUSE: 
    ... 
    break; 
} 

そして、あなたは今までの状態を切り替えたい場合は、あなただけのこれはあなたの質問に答え

m_gameState = GameState::PAUSE; 

希望行うことができます:D

ない場合は、私が誤解(ごめん)持っている必要があります。

+0

これは良い解決策ですが、これはメインループをその責任ではない振る舞いで簡単に氾濫させる可能性があります。 @ powergloveというアプローチでは、別のクラスに分けることができます。 – Chringo

+0

これを別のクラスに分けることができます。これは1つのクラスに限定されているわけではありません。 (これは答えとして働いた場合は@powerglove、それをマークしてください、ありがとう) – Nybbit

関連する問題