【问题标题】:C++ Implementing statesC++ 实现状态
【发布时间】:2017-05-24 18:07:23
【问题描述】:

我的问题是: 我正在尝试在我的项目中实施基本的状态管理,但我一直在不断变化的状态。 我的所有状态都在 std::stack<State*> 容器中,并直接从 Application 类或 State 类推送/弹出它们。 问题是当我从 State 类更改当前状态时,它可以在调用渲染方法之前被销毁,这会导致异常。那么我该如何避免呢? PS对不起我的英语,如果我的问题/代码中的某些内容很清楚,请告诉我

应用类:

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

好吧,也许这不是一个真正的问题,而是类似于“如何做”的问题。正如您在我的代码中看到的,我在 mainLoop() 方法中更新和呈现状态。我想弄清楚的是如何管理这些更新,假设状态可以从状态本身更改,而不仅仅是从 stateManager(在我的情况下为 Application 类)

【问题讨论】:

  • 欢迎来到 Stack Overflow。请花时间阅读The Tour 并参考Help Center 中的材料,您可以在这里问什么以及如何问。
  • 您确定堆栈是保存状态的正确数据结构吗?您可能对this 感兴趣。
  • 不确定,也许我可以将其更改为矢量,但总的来说这不是我认为的问题
  • 调试器是解决此类问题的正确工具。 询问 Stack Overflow 之前,您应该逐行浏览您的代码。如需更多帮助,请阅读How to debug small programs (by Eric Lippert)。至少,您应该在edit 您的问题中包含一个重现您的问题的Minimal, Complete, and Verifiable 示例,以及您在调试器中所做的观察。
  • 好吧,也许这不是一个真正的问题,而是类似于“如何做”的问题。正如您在我的代码中看到的,我在 mainLoop() 方法中更新和呈现状态。我想弄清楚的是如何管理这些更新,假设状态可以从状态本身更改,而不仅仅是从 stateManager(在我的情况下为 Application 类)

标签: c++ sfml


【解决方案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

如果不是,那我一定是误会了(对不起)。

【讨论】:

  • 这是一个不错的解决方案,但这很容易使主循环充满不属于其责任的行为。通过@powerglove 采用的方法,他可以将其分成另一个类。
  • 如果你愿意,你可以把它分成另一个类,它不仅限于一个类。 (还有@powerglove,如果这可以作为答案,请务必标记它,谢谢)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-06
相关资源
最近更新 更多