C++游戏状态系统

6 c++ state

好的:我对C++和静态语言都很陌生.来自多年的红宝石(和其他动态语言),我不知道这是否可能.

我一直在制作游戏状态系统......好吧游戏.我希望系统能够让我轻松剪切并粘贴到其他游戏中,而无需进行任何(或极少数)更改.

我想要改进的两件事是状态切换的方式以及状态指针的保存方式.

可能存在任意数量的状态,但在内存中始终存在至少2到3个状态.

丑陋的1号.

目前我有一个状态管理器类,里面有这样的东西:

void StateManager::changeState(StateID nextStateID)
{
    // UNFOCUS THE CURRENT STATE //
    if (currentState())
    {
        currentState()->onUnFocus();

        // DESTROY THE STATE IF IT WANTS IT //
        if(currentState()->isDestroyedOnUnFocus()) {
            destroyCurrentState();
        }
    }

    if (m_GameStates[nextStateID]) {
        // SWITCH TO NEXT STATE //
        setCurrentState(nextStateID);
    }
    else
    {
        // CREATE NEW STATE //
        switch (nextStateID)
        {
        case MainMenuStateID:
            m_GameStates[MainMenuStateID] = new MainMenuState;
            break;
        case GameStateID:
                        m_GameStates[MainMenuStateID] = new GameStates;
            break;
        };
        setCurrentState(nextStateID);
    }

    // FOCUS NEXT STATE //
    currentState()->onFocus();
}
Run Code Online (Sandbox Code Playgroud)

这种方法有效,但我觉得它不是很好.

是否可以传递一种类型?然后打电话给新的吗?

new NextGameState;  // Whatever type that may be.
Run Code Online (Sandbox Code Playgroud)

poloymophism可以帮助吗?所有国家都来自a class State.

丑陋的2号.

我认为需要改进的另一件事是我存储状态的方式.

State* m_GameStates[MaxNumberOfStates];
Run Code Online (Sandbox Code Playgroud)

所有状态都初始化为NULL,因此我可以测试状态是否存在,如果不存在则在需要时创建状态.

它可以正常工作,因为我可以调用当前状态:

m_GameStates[m_CurrentState];
Run Code Online (Sandbox Code Playgroud)

但是,我不喜欢这个有两个原因.当任何时候只有2或3个指针处于活动状态时,如果有一个充满NULL指针的数组,那似乎有点浪费.[编者注:第二个原因是什么?]

vector_ptr想把它变成一个,但没有,因为它会产生额外的复杂性,检查是否存在状态.矢量似乎强化了Ugance No 1.因为我需要有一个列表来检查每个州.

任何建议或方向表示赞赏.

谢谢,菲尔.

jal*_*alf 0

对于你的第一个问题,是的,你可以传递一个类型,但有一些警告。

我在您的问题下添加了评论,要求提供更多信息。在我们明白这一点之前,我真的无法说出应该如何完成,但请阅读模板。

您可以创建一个可以传递类型的函数模板,例如如下所示:

template <typename T>
void Foo() {
  T* x = new T();
  ...
}

Foo<int>() // call Foo with the type T set to 'int'
Run Code Online (Sandbox Code Playgroud)

这样做有一些限制,因为必须在编译时指定类型,但它是一个非常强大的语言功能。

MainState另一种选择可能会更好,因为您似乎在变量 ( ) 和类型 ( )之间存在关联MainMenu,它可能是使用特征类。再说一遍,我不确定在你的情况下具体是如何完成的,因为我们还没有看到该函数的全部内容(特别是 是什么类型MainState,以及它是如何/何时创建的?)

也可能通过多态性来解决问题,但同样,我需要查看更多的上下文来提出解决方案。

对于第二个问题,您可以使用标准库map

#include <map>

// I'm not sure what type m_CurrentState is, so use its type instead of KeyType below
std::map<KeyType, State*> m_GameStates;

// and to perform a lookup in the map:
GameStates[m_CurrentState];
Run Code Online (Sandbox Code Playgroud)

最后,一个非常非常重要的建议:

停止到处使用指针。停止调用new创建新对象。作为一般规则,对象应该在堆栈上创建(而不是Foo* f = new Foo;,只需执行Foo f;

您通常只想复制对象本身,而不是使用指针。或者,创建引用而不是指针。

当你确实需要使用动态内存分配时,你仍然不应该new直接使用。相反,创建一个包装对象,该对象在其构造函数中内部分配所需的内容new,并在析构函数中再次释放它。

如果你正确地做到了这一点,它几乎可以解决内存管理的所有令人头疼的问题。

通用技术称为RAII