Hi,
first of all: great site!
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 customable 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
-
First of all: 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!
-
My second question 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. E.g. 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?
I would really appreciate any answers, as this bothers me for a few days now. Thanks!