C ++实现状态

时间:2017-05-24 18:07:23

标签: c++ sfml

我的问题是: 我正在尝试在我的项目中实施基本的状态管理,并且我坚持改变状态。 我在std::stack<State*>容器中拥有所有状态,并直接从Application类或State类中推送/弹出它们。 问题是当我从State类改变当前状态时,它可以在调用render方法之前销毁,whitch导致exeption。那么我该如何避免这种情况呢? 对不起我的英语,如果我的问题/代码中的内容不清楚,请说出来

申请类:

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

州级:

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

好吧也许这不是一个真正的问题,但是类似于&#34;如何&#34;题。正如您在我的代码中看到的,我在mainLoop()方法中更新并呈现状态。想要弄清楚的是如何管理这些更新,假设状态可以从状态本身改变,而不仅仅是从stateManager(在我的例子中是Application类)

1 个答案:

答案 0 :(得分: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

如果没有,我一定是误解了(抱歉)。