using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Syntriax.Engine.Core.Abstract; using Syntriax.Engine.Core.Factory; namespace Syntriax.Engine.Core; public class GameManager { private IList _gameObjects = new List(Constants.GAME_OBJECTS_SIZE_INITIAL); private IList _drawables = new List(Constants.DRAWABLE_OBJECTS_SIZE_INITIAL); private GameObjectFactory _gameObjectFactory = null!; private GameObjectFactory GameObjectFactory { get { if (_gameObjectFactory is null) _gameObjectFactory = new GameObjectFactory(); return _gameObjectFactory; } } public IList GameObjects => _gameObjects; public void RegisterGameObject(IGameObject gameObject) { if (_gameObjects.Contains(gameObject)) throw new Exception($"{nameof(IGameComponent)} named {gameObject.Name} is already registered to the {nameof(GameManager)}."); Register(gameObject); } public T InstantiateGameObject(params object?[]? args) where T : class, IGameObject { T gameObject = GameObjectFactory.Instantiate(args); Register(gameObject); return gameObject; } public IGameObject RemoveGameObject(IGameObject gameObject) { if (!_gameObjects.Contains(gameObject)) throw new Exception($"{nameof(IGameComponent)} named {gameObject.Name} is not registered to the {nameof(GameManager)}."); Unregister(gameObject); return gameObject; } public void Initialize() { foreach (var gameObject in GameObjects) gameObject.Initialize(); } public void Update(GameTime time) { foreach (var gameObject in GameObjects) gameObject.BehaviourController.Update(time); } public void PreDraw(GameTime time) { foreach (var gameObject in GameObjects) gameObject.BehaviourController.UpdatePreDraw(time); } public void Draw(SpriteBatch spriteBatch) { spriteBatch.Begin(); foreach (var gameObject in GameObjects) if (gameObject.BehaviourController.TryGetBehaviour(out var drawable)) drawable.Draw(spriteBatch); spriteBatch.End(); } ///////////////////////////////////////////////////////////////// private void Unregister(IGameObject gameObject) { gameObject.BehaviourController.OnBehaviourAdded -= OnBehaviourAdd; gameObject.BehaviourController.OnBehaviourRemoved -= OnBehaviourRemove; gameObject.OnFinalized -= OnGameObjectFinalize; if (gameObject.BehaviourController.TryGetBehaviour(out var drawable)) _drawables.Remove(drawable); _gameObjects.Remove(gameObject); } private void Register(IGameObject gameObject) { gameObject.BehaviourController.OnBehaviourAdded += OnBehaviourAdd; gameObject.BehaviourController.OnBehaviourRemoved += OnBehaviourRemove; gameObject.OnFinalized += OnGameObjectFinalize; if (gameObject.BehaviourController.TryGetBehaviour(out var drawable)) _drawables.Add(drawable); _gameObjects.Add(gameObject); } private void OnGameObjectFinalize(IInitialize initialize) { if (initialize is IGameObject gameObject) Unregister(gameObject); } private void OnBehaviourAdd(IBehaviourController controller, IBehaviour behaviour) { if (behaviour is IDrawable drawable) _drawables.Add(drawable); } private void OnBehaviourRemove(IBehaviourController controller, IBehaviour behaviour) { if (behaviour is IDrawable drawable) _drawables.Remove(drawable); } }