2017-05-24 4 views
0

Ma question est: J'essaie de mettre en œuvre la gestion de l'état de base dans mon projet et je suis bloqué au changement d'état. J'ai tous mes états dans std::stack<State*> conteneur, et les pousser/pop directement à partir de la classe Application ou de la classe State. Problème lorsque je change l'état actuel de la classe d'état, il peut être détruit avant l'appel de la méthode de rendu, ce qui entraîne une exception. Alors, comment puis-je éviter cela? PS désolé pour mon anglais et s'il vous plaît me dire si quelque chose dans mon problème/code ISN clairC++ Etats d'implémentation

classe Application:

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

classe État:

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

Ok cela est peut-être pas vraiment une problème, mais quelque chose comme "comment" question. Comme vous pouvez le voir dans mon code, je mets à jour et restitue les états dans la méthode mainLoop(). Ce qu'il faut savoir, c'est comment gérer ces mises à jour, en supposant que cet état peut être changé de l'état lui-même, et pas seulement de stateManager (dans mon cas Application class)

+0

Bienvenue dans Stack Overflow. Veuillez prendre le temps de lire [The Tour] (http://stackoverflow.com/tour) et de consulter le contenu du [Centre d'aide] (http://stackoverflow.com/help/asking) quoi et comment vous pouvez demandez ici. –

+2

Etes-vous sûr qu'une pile est la bonne structure de données pour contenir des états? Vous pourriez être intéressé par [this] (http://makulik.github.io/sttcl/). –

+0

Pas sûr, peut-être je peux le changer en vecteur, mais dans l'ensemble ce n'est pas ce que mon problème est que je pense – joe503

Répondre

1

Ok, donc je suppose que c'est pour un jeu (mais ça ne doit pas être). Au lieu de faire ce que vous faites pour passer d'un état à l'autre, j'utilise une énumération.

enum class GameState { 
    MENU, PLAY, PAUSE 
} 

Ensuite, dans votre tête principale

GameState m_gameState = GameState::MENU; 

Dans votre boucle principale, vous pouvez vérifier ce que l'état actuel est simplement faire

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

ou vous pouvez utiliser une instruction switch

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

Et, si jamais vous voulez changer l'état, vous pouvez juste faire

m_gameState = GameState::PAUSE; 

Hope this répondu à votre question: D

Sinon, je dois avoir mal compris (désolé).

+0

Ceci est une bonne solution, mais cela pourrait facilement inonder la boucle principale d'un comportement qui n'est pas de sa responsabilité. Avec l'approche que prend @ powerglove, il peut séparer cela en une autre classe. – Chringo

+0

Vous pouvez séparer cela en une autre classe si vous le souhaitez, ce n'est pas limité à la seule classe. (Aussi @powerglove si cela a fonctionné comme une réponse, assurez-vous de le marquer, merci) – Nybbit