I am writing a game following an Entity Component-style design pattern, and have run into an issue I have been able to solve, but am not sure if it is a best practice (or if there even is such a thing).
I have a state machine that handles the main states of the game (menu, in-level, paused, background), and an inner state machine in one of the gameplay components that handles more piecemeal game states (new level, level over, next level, game over and summary). I want to let the outer state machine know that the game has ended from the inner component, but it has no reference to the main controller class. Normally, I'd use a protocol to delegate information up the chain, but this seems to me, in my limited ECS experience, to break the paradigm. What I am doing is querying the app delegate for the window's root view controller, and calling convenience methods on it depending on the inner state...this would be a horrendous way to do MVC, but seems like it is fine in ECS.
Could anyone confirm that this is not as terrible as I think it is, or if it is, recommend a new paradigm? It would be greatly appreciated.
Basically it is working like this ( I think it is too much code to post in its entirety):
MainMenuViewController has an ApplicationEntity, which has an ApplicationLifecycleComponent that contains a state machine. On pressing a 'start game' button, the state machine passes into ApplicationGameState.
ApplicationGameState uses a weak reference to the MainMenu VC (which is root) to present a GameViewController that loads a SpriteKit scene. Game logic happens here through a bunch of inner components and state machines that eventually report a 'game over'.
On game over, the ApplicationLifecycle's state machine should exit ApplicationGameState and enter MainMenuState (or any other state, as necessary), but since I can't get at the root VC from the scene, I ask the AppDelegate for the root vc, cast it as a MainMenuViewController, grab its entity and tell its lifecycle component to change state, as below:
if let applicationController = UIApplication.sharedApplication().keyWindow?.rootViewController as? MainMenuViewController {
applicationController.applicationEntity.applicationLifecycleComponent.enterMenuState()
}
Rephrasing the question, should I push a weak reference of the root view controller down the chain from application start to get to this state? Is there a best practice for notifying a higher-level entity that something happened?
For reference, this is my first-ever foray into ECS.