C++ 状态:事件序列不是纯面向对象的

C++ States: Sequence of Events is not very object orientated

我正在努力使我的代码更加面向对象。

我有一个小程序希望完成 2 个非常简单的状态:输入状态和结果状态。

输入状态似乎很容易解决,因为虽然它是图形化的,但它是 "self-updating." 用户在屏幕上放置和移除精灵以产生输入。

结果状态让我很烦,因为我为它生成了一些非常丑陋的代码,根本不是面向对象的。

此状态需要按顺序做事,我正在努力寻找如何使用对象完成此操作的示例。它基本上是一些具有相同对象的动画:这里是一些伪代码。

Static int objectx = 120, object y = 120;
Static int state=0

switch(state)
{
Case 0:
//....move object right
//....once object is far enough right
state = 1;

Case 1:
//....move object down
//....once object is far enough down
state = 2;

...etc

所以我猜它需要转向拥有某种状态引擎,但我正在努力了解如何使用状态完成顺序事件。这些状态始终相同,因此可以硬编码,它们不会根据给定的输入而改变。

如有任何帮助,我们将不胜感激。

更新

也许我们可以把这第二个状态想象成一个二维游戏的过场动画。我们想要一个角色走到屏幕上,说些什么然后走开。

所以我目前的做法是通过 switch 语句管理这部分程序状态。每次我们在程序的 "result" 部分时都会调用此函数,并且我们正在使用 switch 语句来更新精灵的位置。一旦我们到达第一组动作的末尾,我们就会移动到下一个 switch 语句并继续这样做直到它完成。它 有效 但我希望使用“游戏状态” Class,它可以拥有图形和声音的所有权,并适当地移动东西。

注意:由于我没有任何上下文,所以在这里做一些假设。

听起来每个精灵都应该有自己的循环,而不是让整个游戏逻辑围绕精灵移动。 将其改编为面向对象的设计,您可以将每个精灵包装在一些 class:

class NPC : Sprite {
    private:
        Position CurrentPosition;
        int CurrentState;

    public:
        virtual void Think() = 0;
        virtual void Render() = 0;
};

然后你可以从这个class继承特定的精灵:

class GobbledyGook : NPC {
    private:
        const int FinalState = 10;

    public:        
        bool Completed = false;

        void Think() override {
            if(Completed)
                return;

            switch(CurrentState) {
                // ... repeating logic here ...
            }

            CurrentState++;

            if(CurrentState == FinalState)
                Completed = true;
        }

        void Render() override {
            // ... draw the sprite ...
        }
}

然后您可以从主游戏逻辑更新每个精灵:

// Spawn a GobbledyGook into existence.
my_npcs.insert(new GobbledyGook());

// In frame logic.
bool finished = true;
for( NPC* n : my_npcs )
{
    n->Think();
    if(!n->Completed)
        finished = false;
}

if(finished) {
    // Result state.
}

// In render logic.
for( NPC* n : my_npcs )
{
    n->Render();
}

你自然也可以对整个场景采用这种逻辑:

class Intro : Cutscene {
    private:
        vector<NPC*> SceneSprites;

    public:
        void Think() override {
            switch(CurrentState) {
                ...
            }

            for( NPC* n : SceneSprites ) {
                n->Think();
            }
        }

        ...
};

至于是否应该删除或更改状态的使用,您打算从中获得什么?

如果不了解当前方法的所有缺陷,就很难推荐不同的方法。