I have asked a question similar to this before but I cannot move forward with my engine without fixing the State Machine. In my old design, the systems hold the needed components and updated them as needed and the states hold the systems they need. Like "Play" holds graphics,physics,input,ai,gui; the "MainMenu" holds gui,input. Also, the states are not hard written to the engine; one can create any type of a system they want with the needed components. The problem was that new systems are created for each state; for example there would be multiple input systems in the lifecycle of the application if more than one state has input system.
As my engine become more complex, I decided to change the design to something similar to Artemis Framework. So, here is the new design:
The systems are created ONCE only and their pointers are passed to the needed states. Each state holds a component map. The first parameter of the component is the pointer of the system. The second parameter is of type ComponentHolder. A component holder is basically an abstract class of different lists of components. For example a GraphicsComponentHolder holds 3 lists {list<GraphicsComponent*>, list<CameraComponent*>, list<LightComponent*>}
Example Snippet:
class GameState {
private:
std::map<Controller*, ComponentHolder*> mControllers;
std::map<View*, ComponentHolder*> mViews;
public:
void update(Real time) {
for(auto &controller : mController)
controller.first->update(time, controller.second);
}
void render() {
for(auto &view : mViews)
view.first->render(view.second);
}
};
class HordeCameraController : public Controller {
public:
void updateNode(SceneNode * node) {
//...
}
void update(Real dt, ComponentHolder * holder_) {
auto holder = static_cast<HordeComponentHolder*>(holder_);
for(auto graphics : holder->getGraphicsComponents())
updateNode(graphics);
for(auto camera : holder->getCameraComponents())
updateNode(camera);
for(auto light : holder->getLightComponents())
updateNode(light);
}
};
class HordeCameraView : public View {
public:
void render(ComponentHolder * holder_) {
auto holder = static_cast<HordeComponentHolder*>(holder_);
for(auto camera : holder->getCameraComponents())
h3dRender(camera->getNode());
}
};
Is there another way I can build this? Or should I do it this way? Should I just update the component holder when state changes or do something different. I am very noob at state management, so I really need help on designing on.
Thanks,
Gasim