public MainPage() { InitializeComponent(); SoundPlayer.FillDictionary(App.Current.Resources.MergedDictionaries[0]); SoundPlayer.BackgroundMusic.FillBgDictionary(App.Current.Resources.MergedDictionaries[1]); TextHandler.FillDictionary(App.Current.Resources.MergedDictionaries[2]); this.GotFocus += MainPageGotFocus; this.LostFocus += MainPageLostFocus; _keyHandler = new KeyHandler(this); _menuEngine = new MenuEngine(this.gameSurface); _menuEngine.Updated += MenuEngineUpdated; _levelEngine = new LevelEngine(new Canvas()); _levelEngine.Renewed += LevelEngineRenewed; _hudEngine = new HudEngine(new Canvas()); _scoreEngine = new ScoreEngine(new Canvas(), 10); Level.Player = Player = new Player(); _renderNotifier = new RenderNotifier(this); _renderNotifier.AddObservedChild(this.gameSurface); _renderNotifier.RenderComplete += RenderNotifierRenderComplete; _mainLoop = new CompositionTargetGameLoop(); _mainLoop.Update += MainLoopUpdate; }
public void SetSequence(EnemyDeathEngine enemyDeathEngine, ScoreEngine scoreEngine, DamageSoundEngine damageSoundEngine, EnemyAnimationEngine enemyAnimationEngine, EnemySpawnerEngine enemySpawnerEngine) { base.SetSequence( new Steps //sequence of steps, this is a dictionary! ( new Step { @from = enemyDeathEngine, to = new To ( //TIP: use GO To Type Declaration to go directly to the Class code of the //engine instance scoreEngine, damageSoundEngine ) }, new Step { //second step @from = enemyAnimationEngine, //after the death animation is actually finished to = new To ( enemySpawnerEngine //call the spawner engine ) } ) ); }
public LevelHolder(LevelEngine levelEngine, HudEngine hudEngine, ScoreEngine scoreEngine) : base(_menu) { if (levelEngine == null) { throw new ArgumentNullException("No LevelEngine defined!"); } _levelEngine = levelEngine; _levelEngine.Started += LevelEngineStarted; _levelEngine.BeforeNextLevel += LevelEngineBeforeNextLevel; _levelEngine.Finished += LevelEngineFinished; if (hudEngine == null) { throw new ArgumentNullException("No HudEngine defined!"); } _hudEngine = hudEngine; _hudEngine.TimesUp += TimesUp; if (scoreEngine == null) { throw new ArgumentNullException("No ScoreEngine defined!"); } _scoreEngine = scoreEngine; ConnectPlayer(); _levelSurface = _menu.FindName("levelSurface") as Canvas; if (_levelSurface == null) { throw new NotImplementedException("levelSurface canvas not implemented"); } _levelSurface.Children.Add(_levelEngine.Container); _hudSurface = _menu.FindName("hudSurface") as Canvas; if (_hudSurface == null) { throw new NotImplementedException("hudSurface canvas not implemented"); } _hudSurface.Children.Add(_hudEngine.Container); this.Shown += LevelHolderShown; }
/// <summary> /// Before to start a review of Svelto.ECS terminologies: /// - Entity: /// it must be a real and concrete entity that you can explain /// in terms of game design. The name of each entity should reflect /// a specific concept from the game design domain /// - IComponents: /// Components must be seen as data holders. There are implementing /// exceptions, but logically it must be still see as a group /// of readable or writeable data. /// In Svelto.ECS components are always interfaces declaring /// Setters and Getters of ValueTypes. DispatchOnSet /// and DispatchOnChange must not be seen as events, but /// as pushing of data instead of data polling, similar /// to the concept of DataBinding. /// - Implementors: /// Being components interfaces, they must be implemented through /// Implementors. The relation Implementors to Components /// is not 1:1 so that you can, if logic, group several /// components in one implementor. This allows to easily /// share data between components. Implementors also act /// as bridge between the platform and Svelto.ECS. /// Since Components can hold only value types, Implementors /// are the objects that can interact directly with the platform /// objects, I.E.: RigidBody, Transform and so on. /// Note: IComponents must hold only valuetypes for /// code design purposes and not optmization purposes. /// The reason is that all the logic must lie in the engines /// so Components cannot hold references to instances that can /// expose functions with logic. /// - Engines: /// Where all the logic lies. Engines operates on EntityViews /// - EntityViews: /// EntityViews maps EntityComponents. The Engines can't /// access directly to each entity (as a single set of components), but /// through a component sets defined by EntityView. /// They act as a component filters and expose only the entity components /// that the Engine is interested in. /// EntityViews are actually defined by the need of the Engine so they /// come together with the engine and in the same namespace of the engine. /// - EntityStructs: /// In order to write Data Oriented Cache Friendly code, Svelto.ECS /// also support EntityStructs. Please check other examples to /// understand how to use them. However know that this kind of /// optimizations is very limited to special circumstances /// so the flexibility of EntityViews is most of the times what you need. /// - EntityDescriptors: /// Gives a way to formalize your Entity in svelto.ECS, it also /// groups the EntityViews that must be generated once the /// Entity is built /// </summary> void SetupEnginesAndEntities() { //The Engines Root is the core of Svelto.ECS. You must NEVER inject the EngineRoot //as it is, therefore the composition root must hold a reference or it will be //GCed. //the UnitySumbmissionEntityViewScheduler is the scheduler that is used by the EnginesRoot to know //when to inject the EntityViews. You shouldn't use a custom one unless you know what you //are doing or you are not working with Unity. _enginesRoot = new EnginesRoot(new UnitySumbmissionEntityViewScheduler()); //Engines root can never be held by anything else than the context itself to avoid leaks //That's why the EntityFactory and EntityFunctions are generated. //The EntityFactory can be injected inside factories (or engine acting as factories) //to build new entities dynamically _entityFactory = _enginesRoot.GenerateEntityFactory(); //The entity functions is a set of utility operations on Entities, including //removing an entity. I couldn't find a better name so far. var entityFunctions = _enginesRoot.GenerateEntityFunctions(); //GameObjectFactory allows to create GameObjects without using the Static //method GameObject.Instantiate. While it seems a complication //it's important to keep the engines testable and not //coupled with hard dependencies references (read my articles to understand //how dependency injection works and why solving dependencies //with static classes and singletons is a terrible mistake) GameObjectFactory factory = new GameObjectFactory(); //the ISequencer is one of the 3 official ways available in Svelto.ECS //to communicate. They are mainly used for two specific cases: //1) specify a strict execution order between engines (engine logic //is executed horizontally instead than vertically, I will talk about this //in my articles). 2) filter a data token passed as parameter through //engines. The ISequencer is also not the common way to communicate //between engines Sequencer playerDamageSequence = new Sequencer(); Sequencer enemyDamageSequence = new Sequencer(); //wrap non testable unity static classes, so that //can be mocked if needed. IRayCaster rayCaster = new RayCaster(); ITime time = new Time(); //Player related engines. ALL the dependecies must be solved at this point //through constructor injection. var playerHealthEngine = new HealthEngine(playerDamageSequence); var playerShootingEngine = new PlayerGunShootingEngine(enemyDamageSequence, rayCaster, time); var playerMovementEngine = new PlayerMovementEngine(rayCaster, time); var playerAnimationEngine = new PlayerAnimationEngine(); var playerDeathEngine = new PlayerDeathEngine(entityFunctions); //Enemy related engines var enemyAnimationEngine = new EnemyAnimationEngine(time); //HealthEngine is a different object for the enemy because it uses a different sequence var enemyHealthEngine = new HealthEngine(enemyDamageSequence); var enemyAttackEngine = new EnemyAttackEngine(playerDamageSequence, time); var enemyMovementEngine = new EnemyMovementEngine(); var enemySpawnerEngine = new EnemySpawnerEngine(factory, _entityFactory); var enemyDeathEngine = new EnemyDeathEngine(entityFunctions); //hud and sound engines var hudEngine = new HUDEngine(time); var damageSoundEngine = new DamageSoundEngine(); var scoreEngine = new ScoreEngine(); //The ISequencer implementaton is very simple, but allows to perform //complex concatenation including loops and conditional branching. playerDamageSequence.SetSequence( new Steps //sequence of steps, this is a dictionary! { { //first step enemyAttackEngine, //this step can be triggered only by this engine through the Next function new To //this step can lead only to one branch { //this is the only engine that will be called when enemyAttackEngine triggers Next() new IStep[] { playerHealthEngine } } }, { //second step playerHealthEngine, //this step can be triggered only by this engine through the Next function new To //once the playerHealthEngine calls step, all these engines will be called at once //depending by the condition a different set of engines will be triggered. The //order of the engines triggered is guaranteed. { //these engines will be called when the Next function is called with the DamageCondition.damage set { DamageCondition.Damage, new IStep[] { hudEngine, damageSoundEngine } }, //these engines will be called when the Next function is called with the DamageCondition.dead set { DamageCondition.Dead, new IStep[] { hudEngine, damageSoundEngine, playerMovementEngine, playerAnimationEngine, enemyAnimationEngine, playerDeathEngine } } } } } ); enemyDamageSequence.SetSequence( new Steps { { playerShootingEngine, new To { //in every case go to enemyHealthEngine new IStep[] { enemyHealthEngine } } }, { enemyHealthEngine, new To { { DamageCondition.Damage, new IStep[] { enemyAnimationEngine, damageSoundEngine } }, { DamageCondition.Dead, new IStep[] { scoreEngine, enemyMovementEngine, enemyAnimationEngine, enemySpawnerEngine, damageSoundEngine, enemyDeathEngine } }, } } } ); //Mandatory step to make engines work //Player engines _enginesRoot.AddEngine(playerMovementEngine); _enginesRoot.AddEngine(playerAnimationEngine); _enginesRoot.AddEngine(playerShootingEngine); _enginesRoot.AddEngine(playerHealthEngine); _enginesRoot.AddEngine(new PlayerInputEngine()); _enginesRoot.AddEngine(new PlayerGunShootingFXsEngine()); //enemy engines _enginesRoot.AddEngine(enemySpawnerEngine); _enginesRoot.AddEngine(enemyAttackEngine); _enginesRoot.AddEngine(enemyMovementEngine); _enginesRoot.AddEngine(enemyAnimationEngine); _enginesRoot.AddEngine(enemyHealthEngine); _enginesRoot.AddEngine(enemyDeathEngine); //other engines _enginesRoot.AddEngine(new CameraFollowTargetEngine(time)); _enginesRoot.AddEngine(damageSoundEngine); _enginesRoot.AddEngine(hudEngine); _enginesRoot.AddEngine(scoreEngine); }
public string Answer(string userId, string utterance) { BotContext context = this.GetValidContext(userId); bool isSingleContact = this.IsSingleContact(ref utterance); if (context == null) { LUInfo luInfo = Understand(utterance, isSingleContact); if (luInfo.GetType() == typeof(TestLUInfo)) { context = InitTFContext(userId, (TestLUInfo)luInfo); } else if (luInfo.GetType() == typeof(ExamLUInfo)) { context = InitESContext(userId, (ExamLUInfo)luInfo); } else if (luInfo.GetType() == typeof(ScoreLUInfo)) { context = InitScoreContext(userId, (ScoreLUInfo)luInfo); } else { context = initPSAContext(userId, luInfo); } cManager.CreateContext(context, userId); } else { if (context.type == ContextType.TaskFlowContext && isSingleContact) { TaskFlowContext tfContext = (TaskFlowContext)context; context = updateTFContext(ref tfContext, utterance); } else if (context.type == ContextType.ExamSuitContext && isSingleContact) { ExamSuitContext esContext = (ExamSuitContext)context; context = updateESContext(ref esContext, utterance); } else if (context.type == ContextType.ScoreContext && isSingleContact) { ScoreContext scContext = (ScoreContext)context; context = updateSCContext(ref scContext, utterance); } else { LUInfo luInfo = Understand(utterance, isSingleContact); if (context.type == ContextType.PSAContext) { PSAContext psacontext = (PSAContext)context; context = updatePSAContext(ref psacontext, luInfo); } else { return("[Error]: Unknown Context Type."); } } } string answer = null; switch (context.type) { case ContextType.ScoreContext: ScoreEngine engineS = new ScoreEngine(); ScoreContext scContext = (ScoreContext)context; answer = engineS.Answer(userId, ref scContext); if (scContext.IsInTesting) { cManager.UpdateContext(scContext, userId); } else { cManager.RemoveContext(userId); } break; case ContextType.PSAContext: ChatTableEngine engine = new ChatTableEngine(); PSAContext psacontext = (PSAContext)context; answer = engine.Answer(userId, ref psacontext); cManager.UpdateContext(psacontext, userId); break; case ContextType.TaskFlowContext: TestEngine engineT = new TestEngine(); TaskFlowContext tfContext = (TaskFlowContext)context; answer = engineT.Answer(userId, ref tfContext); if (tfContext.IsInTesting) { cManager.UpdateContext(tfContext, userId); } else { cManager.RemoveContext(userId); } break; case ContextType.ExamSuitContext: ExamSuitContext esContext = (ExamSuitContext)context; DICSExamSrv taskSrv = new DICSExamSrv(); string userInput = esContext.UserInput; switch (esContext.status) { case ESStatus.Started: ExamSuitContext cachedContext = this.GetCachedESContext(userId); answer = taskSrv.StartTest(ref esContext, cachedContext); break; case ESStatus.Restarted: answer = taskSrv.ContinueOrRefresh(ref esContext, userInput); break; case ESStatus.OnGoing: answer = taskSrv.ReceiveUserAnswer(ref esContext, userInput); break; } if (esContext.status == ESStatus.Finished || esContext.status == ESStatus.Aborded) { cManager.RemoveContext(userId); } else if (esContext.status == ESStatus.Paused) { cManager.StoreESContext(esContext, userId); cManager.RemoveContext(userId); } else { cManager.UpdateContext(esContext, userId); } break; } return(answer); }
/// <summary> /// Before to start a review of Svelto.ECS terminologies: /// - Entity: /// it must be a real and concrete entity that you can explain /// in terms of game design. The name of each entity should reflect /// a specific concept from the game design domain /// - Engines (Systems): /// Where all the logic lies. Engines operates on EntityViews or EntityStructs /// - EntityViews and EntitiyViewStructs: /// EntityViews maps Entity Components. The Engines can't /// access directly to each entity (as a single set of components), but /// through component sets defined by the EntityView. /// They act as component filters and expose only the entity components /// that the Engine is interested in. /// EntityViews are actually defined with the Engine so they /// come together with the engine and in the same namespace of the engine. /// EntityViewStructs should always be used, while EntityViews as /// class use should be considered an exception. /// - Component Interfaces: /// Components must be seen as data holders. There may be implementation /// exceptions, but the interface must declare a group /// of readable and/or writeable data. /// In Svelto.ECS components are always interfaces declaring /// Setters and Getters of Value Types. DispatchOnSet /// and DispatchOnChange must not be seen as events, but /// as pushing of data instead of data polling, similar /// to the concept of DataBinding. /// - Implementors: /// Being components interfaces, they must be implemented through /// Implementors. The relation Implementors to Components /// is not 1:1 so that you can group several /// components into fewer implementors. This allows to easily /// share data between components. Implementors also act /// as bridge between the platform and Svelto.ECS. /// Since Components can hold only value types, Implementors /// are the objects that can interact directly with the platform /// objects, I.E.: RigidBody, Transform and so on. /// Note: IComponents must hold only valuetypes for /// code design purposes and not optmization purposes. /// The reason is that all the logic must lie in the engines /// so Components cannot hold references to instances that can /// expose functions with logic. /// - EntityStructs: /// In order to write Data Oriented Cache Friendly and allocation 0 code, Svelto.ECS /// also supports EntityStructs. /// - EntityDescriptors: /// Gives a way to formalize your Entity in svelto.ECS, it also /// defoines the EntityViews, EntityStructs and EntityViewStructs that must be generated once the /// Entity is built /// </summary> void SetupEngines() { //The Engines Root is the core of Svelto.ECS. You must NEVER inject the EngineRoot //as it is, therefore the composition root must hold a reference or it will be //GCed. //the UnitySumbmissionEntityViewScheduler is the scheduler that is used by the EnginesRoot to know //when to inject the EntityViews. You shouldn't use a custom one unless you know what you //are doing or you are not working with Unity. _enginesRoot = new EnginesRoot(new UnityEntitySubmissionScheduler()); //Engines root can never be held by anything else than the context itself to avoid leaks //That's why the EntityFactory and EntityFunctions are generated. //The EntityFactory can be injected inside factories (or engine acting as factories) //to build new entities dynamically _entityFactory = _enginesRoot.GenerateEntityFactory(); //The entity functions is a set of utility operations on Entities, including //removing an entity. I couldn't find a better name so far. var entityFunctions = _enginesRoot.GenerateEntityFunctions(); //the ISequencer is one of the 2 official ways available in Svelto.ECS //to communicate. They are mainly used for two specific cases: //1) specify a strict execution order between engines (engine logic //is executed horizontally instead than vertically, I will talk about this //in my articles). 2) filter a data token passed as parameter through //engines. The ISequencer is also not the common way to communicate //between engines PlayerDeathSequencer playerDeathSequence = new PlayerDeathSequencer(); EnemyDeathSequencer enemyDeathSequence = new EnemyDeathSequencer(); //wrap non testable unity static classes, so that //can be mocked if needed. IRayCaster rayCaster = new RayCaster(); ITime time = new Time(); //Player related engines. ALL the dependencies must be solved at this point //through constructor injection. var playerShootingEngine = new PlayerGunShootingEngine(rayCaster, time); var playerMovementEngine = new PlayerMovementEngine(rayCaster, time); var playerAnimationEngine = new PlayerAnimationEngine(); var playerDeathEngine = new PlayerDeathEngine(playerDeathSequence, entityFunctions); //Enemy related engines var enemyAnimationEngine = new EnemyAnimationEngine(time, enemyDeathSequence, entityFunctions); var enemyAttackEngine = new EnemyAttackEngine(time); var enemyMovementEngine = new EnemyMovementEngine(); //GameObjectFactory allows to create GameObjects without using the Static //method GameObject.Instantiate. While it seems a complication //it's important to keep the engines testable and not //coupled with hard dependencies references (read my articles to understand //how dependency injection works and why solving dependencies //with static classes and singletons is a terrible mistake) GameObjectFactory factory = new GameObjectFactory(); //Factory is one of the few patterns that work very well with ECS. Its use is highly encouraged IEnemyFactory enemyFactory = new EnemyFactory(factory, _entityFactory); var enemySpawnerEngine = new EnemySpawnerEngine(enemyFactory, entityFunctions); var enemyDeathEngine = new EnemyDeathEngine(entityFunctions, enemyDeathSequence); //hud and sound engines var hudEngine = new HUDEngine(time); var damageSoundEngine = new DamageSoundEngine(); var scoreEngine = new ScoreEngine(); //The ISequencer implementation is very simple, but allows to perform //complex concatenation including loops and conditional branching. //These two sequencers are a real stretch and are shown only for explanatory purposes. //Please do not see sequencers as a way to dispatch or broadcast events, they are meant only and exclusively //to guarantee the order of execution of the involved engines. //For this reason the use of sequencers is and must be actually rare, as perfectly encapsulated engines //do not need to be executed in specific order. //a Sequencer can: //- ensure the order of execution through one step only (one step executes in order several engines) //- ensure the order of execution through several steps. Each engine inside each step has the responsibility //to trigger the next step through the use of the Next() function //- create paths with branches and loop using the Condition parameter. playerDeathSequence.SetSequence( new Steps //sequence of steps, this is a dictionary! { { /*from: */ playerDeathEngine, //when the player dies /*to: */ new To <PlayerDeathCondition> //all these engines in the list will be called in order (which in this //case was not important at all, so stretched!!) { { PlayerDeathCondition.Death, playerMovementEngine, playerAnimationEngine, enemyAnimationEngine, damageSoundEngine, hudEngine } } } } ); enemyDeathSequence.SetSequence( new Steps { { //first step enemyDeathEngine, new To <EnemyDeathCondition> { //TIP: use GO To Type Declaration to go directly to the Class code of the //engine instance { EnemyDeathCondition.Death, scoreEngine, enemyAnimationEngine } } }, { //second step enemyAnimationEngine, //after the death animation is actually finished new To <EnemyDeathCondition> { { EnemyDeathCondition.Death, enemySpawnerEngine } //call the spawner engine } } } ); //All the logic of the game must lie inside engines //Player engines _enginesRoot.AddEngine(playerMovementEngine); _enginesRoot.AddEngine(playerAnimationEngine); _enginesRoot.AddEngine(playerShootingEngine); _enginesRoot.AddEngine(new PlayerInputEngine()); _enginesRoot.AddEngine(new PlayerGunShootingFXsEngine()); _enginesRoot.AddEngine(playerDeathEngine); //enemy engines _enginesRoot.AddEngine(enemySpawnerEngine); _enginesRoot.AddEngine(enemyAttackEngine); _enginesRoot.AddEngine(enemyMovementEngine); _enginesRoot.AddEngine(enemyAnimationEngine); _enginesRoot.AddEngine(enemyDeathEngine); //other engines _enginesRoot.AddEngine(new ApplyingDamageToTargetsEngine()); _enginesRoot.AddEngine(new CameraFollowTargetEngine(time)); _enginesRoot.AddEngine(new CharactersDeathEngine()); _enginesRoot.AddEngine(damageSoundEngine); _enginesRoot.AddEngine(hudEngine); _enginesRoot.AddEngine(scoreEngine); }
public Form1() { InitializeComponent(); ScoreEngine = new ScoreEngine(); }
public CalculateRiskProfileService(ScoreEngine scoreEngine) { _scoreEngine = scoreEngine; }
/// <summary> /// Before to start, let's review some of the Svelto.ECS terms: /// - Entity: /// it must be a real and concrete entity that you can explain in terms of game design. The name of each /// entity should reflect a specific concept from the game design domain /// - Engines (Systems): /// Where all the logic lies. Engines operates on EntityViewStructs and EntityStructs /// - EntityStructs: /// EntityStructs is the preferred way to store entity data. They are just plain structs of pure data (no /// objects) /// - EntityViewStructs: /// EntityViewStructs are used to wrap Objects that come from OOP libraries. You will never use it unless /// you are forced to mix your ECS code with OOP code because of external libraries or platforms. /// The Objects are known to svelto through Component Interfaces. /// - Component Interfaces: /// Components must be seen as data holders. In Svelto.ECS components are always interfaces declaring /// Setters and Getters of Value Types coming from the Objects they wrap /// - Implementors: /// The components interfaces must be implemented through Implementors and the implementors are the /// Objects you need to wrap. /// - EntityDescriptors: /// Gives a way to formalise your Entity, it also defines the EntityStructs and EntityViewStructs that must /// be generated once the Entity is built /// </summary> void SetupEngines() { //The Engines Root is the core of Svelto.ECS. You shouldn't inject the EngineRoot, //therefore the composition root must hold a reference or it will be GCed. //the UnitySumbmissionEntityViewScheduler is the scheduler that is used by the EnginesRoot to know //when to submit the entities. Custom ones can be created for special cases. _unityEntitySubmissionScheduler = new UnityEntitySubmissionScheduler(); _enginesRoot = new EnginesRoot(_unityEntitySubmissionScheduler); //The EntityFactory can be injected inside factories (or engine acting as factories) to build new entities //dynamically _entityFactory = _enginesRoot.GenerateEntityFactory(); //The entity functions is a set of utility operations on Entities, including removing an entity. I couldn't //find a better name so far. var entityFunctions = _enginesRoot.GenerateEntityFunctions(); //Sequencers are the official way to guarantee order between engines, but may not be the best way for //your product. var playerDeathSequence = new PlayerDeathSequencer(); var enemyDeathSequence = new EnemyDeathSequencer(); //wrap non testable unity static classes, so that can be mocked if needed. IRayCaster rayCaster = new RayCaster(); ITime time = new Time(); //Player related engines. ALL the dependencies must be solved at this point through constructor injection. var playerShootingEngine = new PlayerGunShootingEngine(rayCaster, time); var playerMovementEngine = new PlayerMovementEngine(rayCaster, time); var playerAnimationEngine = new PlayerAnimationEngine(); var playerDeathEngine = new PlayerDeathEngine(playerDeathSequence, entityFunctions); //Enemy related engines var enemyAnimationEngine = new EnemyAnimationEngine(time, enemyDeathSequence, entityFunctions); var enemyAttackEngine = new EnemyAttackEngine(time); var enemyMovementEngine = new EnemyMovementEngine(); //GameObjectFactory allows to create GameObjects without using the Static method GameObject.Instantiate. //While it seems a complication it's important to keep the engines testable and not coupled with hard //dependencies var gameObjectFactory = new GameObjectFactory(); //Factory is one of the few patterns that work very well with ECS. Its use is highly encouraged var enemyFactory = new EnemyFactory(gameObjectFactory, _entityFactory); var enemySpawnerEngine = new EnemySpawnerEngine(enemyFactory, entityFunctions); var enemyDeathEngine = new EnemyDeathEngine(entityFunctions, enemyDeathSequence); //hud and sound engines var hudEngine = new HUDEngine(time); var damageSoundEngine = new DamageSoundEngine(); var scoreEngine = new ScoreEngine(); //The ISequencer implementation is very simple, but allows to perform //complex concatenation including loops and conditional branching. //These two sequencers are a real stretch and are shown only for explanatory purposes. //Please do not see sequencers as a way to dispatch or broadcast events, they are meant only and exclusively //to guarantee the order of execution of the involved engines. //For this reason the use of sequencers is and must be actually rare, as perfectly encapsulated engines //do not need to be executed in specific order. //a Sequencer can: //- ensure the order of execution through one step only (one step executes in order several engines) //- ensure the order of execution through several steps. Each engine inside each step has the responsibility //to trigger the next step through the use of the Next() function //- create paths with branches and loop using the Condition parameter. playerDeathSequence.SetSequence(playerDeathEngine, playerMovementEngine, playerAnimationEngine, enemyAnimationEngine, damageSoundEngine, hudEngine); enemyDeathSequence.SetSequence(enemyDeathEngine, scoreEngine, damageSoundEngine, enemyAnimationEngine, enemySpawnerEngine); //All the logic of the game must lie inside engines //Player engines _enginesRoot.AddEngine(playerMovementEngine); _enginesRoot.AddEngine(playerAnimationEngine); _enginesRoot.AddEngine(playerShootingEngine); _enginesRoot.AddEngine(new PlayerInputEngine()); _enginesRoot.AddEngine(new PlayerGunShootingFXsEngine()); _enginesRoot.AddEngine(playerDeathEngine); _enginesRoot.AddEngine(new PlayerSpawnerEngine(gameObjectFactory, _entityFactory)); //enemy engines _enginesRoot.AddEngine(enemySpawnerEngine); _enginesRoot.AddEngine(enemyAttackEngine); _enginesRoot.AddEngine(enemyMovementEngine); _enginesRoot.AddEngine(enemyAnimationEngine); _enginesRoot.AddEngine(enemyDeathEngine); //other engines _enginesRoot.AddEngine(new ApplyingDamageToTargetsEngine()); _enginesRoot.AddEngine(new CameraFollowTargetEngine(time)); _enginesRoot.AddEngine(new CharactersDeathEngine()); _enginesRoot.AddEngine(damageSoundEngine); _enginesRoot.AddEngine(hudEngine); _enginesRoot.AddEngine(scoreEngine); }