2017-05-24 94 views
0

我的问题是: 我试图在我的项目中实现基本的状态管理,我坚持改变状态。 我的所有状态都在std::stack<State*>容器中,并直接从应用程序类或状态类推送/弹出它们。 问题是当我从状态类改变当前状态时,它可以在渲染方法调用之前销毁,结果在exeption中。那么我如何避免这种情况呢? PS对不起,我的英语和请说我如果事情在我的问题/代码ISN明确C++实现状态

应用类:

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()方法中更新和渲染状态。什么IM捆绑弄清楚是如何管理这些更新,asuming该状态可以从国家本身被改变,不仅从stateManager(在我的情况下应用类)

+0

欢迎来到Stack Overflow。请花些时间阅读[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

如果你愿意,你可以把它分成另一个类,它不仅限于一个类。 (也@powerglove如果这作为一个答案,一定要标记它,谢谢) – Nybbit