3
\$\begingroup\$

I am currently creating a game engine for educational purposes.

ECS Design Pattern

The first design pattern I've included is the Entity/Component/System pattern. Therefore I've got a base singleton class called cEngine, which contains all systems (PhysicsSystem, GraphicsSystem, etc.) so it can update them on each frame.

void cEngine::Run() 
{
    while( m_Run ) 
    {
        m_Timer.Update();
        for(int i = 0; i < m_Systems.size(); ++i)
            m_Systems.at(i)->Update();
            //NOTE: I will add a SystemManager to update them in the proper order
    }
}

Also, I can create new entities (actually just IDs) and add different components (position, velocity, renderable, ...), which then get saved in the right system. So for example, the position and the velocity components will be saved in the physics system, as this one is responsible for modifying those values. Other systems, however, may have a pointer to those components, because they may need those values (the graphic system for example needs the positional information, but won't modify it).

State Design Pattern

The second design pattern I use is a state system:

class iState 
{
    virtual void Init() {}
    virtual void Quit() {}
    virtual void Update() {}
    virtual void UpdatePause() {}
    virtual void Obscuring() {} //call when another state gets pushed
    virtual void Revealed() {} //call when upper state gets poped
private:
    bool m_isActive; //true, when it is at the top of the state stack
};

The user will be able to create customizable states (overwrite the virtual functions), which then get pushed onto the StateStack. Those functions will be called properly for every state by the StateManager class.

class cStateManager 
{
    void Init();
    void Update();
    void Quit();    

    void PushState( iState* state );
    void PopState();
    void ChangeState( iState* state );
private:
    std::vector<iState*> m_stateStack;
};

Questions

  1. Is this the right choice? In my opinion this design is pretty good, as it is easy for the user and it should have good performance. However, I appreciate suggestions!

  2. This is related to Input Handling. My design would've been a singleton Input class.

    class cInput
    {
        void Update();
    
        bool wasKeyPressed(int key);
        bool wasKeyReleased(int key);
    
        bool isKeyDown(int key);
        bool isKeyUp()int key);
    
    private:
        //...
    }
    

    Once again, the engine class would Update() this class every frame, so it would always have the right key information. The huge benefit by not handling this class as a system, but as a segregated singleton class is, that the user simply can create a new state, create some entities in it, and easily handle input in the virtual Update() function of that state.

    Something like this:

    //overwriting virtual state functions
    void Init(){
        id = cEngine->AddEntity();
    }
    
    void Update(){
        //add some components, bla bla...
    
        //simple input handling
        if(cInput->IsKeyDown(KEY_W)){
            //do something...
        }
    
        if(cInput->WasKeyPressed(KEY_A)){
            //do something
        }
    }
    

    As I've already said, in my opinion this "hybrid" design, which does not see the Input as another ECS system, but as a "independent" class is better and much more comfortable for the user than a "input component". However, I haven't seen this pattern on the Internet, which makes me a little bit insecure.

    Did I miss one huge benefit of an input component or a huge disadvantage with this approach?

\$\endgroup\$

closed as off-topic by Simon Forsberg, RubberDuck, Mathieu Guindon, Brythan, ChrisWue Dec 20 '14 at 17:30

This question appears to be off-topic. The users who voted to close gave this specific reason:

If this question can be reworded to fit the rules in the help center, please edit the question.

  • \$\begingroup\$ Sorry for being late to pay attention to this, but it is virtually impossible to make a good answer here without doing a lot of guesswork and "reading between the lines". I have to consider this "example code". There's a lot of context missing. \$\endgroup\$ – Simon Forsberg Dec 20 '14 at 13:01
3
\$\begingroup\$

Not having seen a given pattern usually means that you didn't use exactly the right search string, or you've modified a pattern that already exists enough so it looks different, so I wouldn't worry about finding solutions that you haven't seen before.

Having a class handling input is the way that I'd initially go to design the structure, unless there was a particularly compelling reason to do it in another way. I'd have my key presses push an Event onto a stack, which can be popped somewhere else. So for instance, if the 'W' key was pressed, I'd push a "Forwards" event (or whatever was relevant), onto a message stack. This check would be within an Update() function of the Input class.

Later on, I'd pass either that message, or an interpretation of that message to the entity that it was relevant to so that it could handle the instruction. This would mean that as long as the message name doesn't change, it shouldn't affect the rest of the system what form of input you're using, as long as it sends those messages.

\$\endgroup\$
1
\$\begingroup\$

A nice thing about using an Input Component is that you can easily detach it from one entity and attaching it to another entity.

Unfortunately you have not posted your exact code in this question, making it a bit of guesswork to fill in the blanks, but my guess is that your current code is directly tied to a specific entity which is supposed to be "controllable" by the human player.

This is where Entity Component System has an advantage. It is Single Responsibility Principle at it's very best, and it decouples your different classes, a lot. Right now all your "states" that are making use of the Input "singleton" is directly tied to it. Reducing their reusability greatly.

I don't think that the Entity Component System approach should be mixed up with the State Design Pattern as you have done. If anything, you can have the State as a Component inside your ECS, and then have a System for each possible state.

Having more context of your actual game would have helped significantly here though.

\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.