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 : IInitialize { public Action? OnInitialized { get; set; } = null; public Action? OnFinalized { get; set; } = null; public Action? OnStateEnableAssigned { get; set; } = null; private IList _gameObjects = new List(Constants.GAME_OBJECTS_SIZE_INITIAL); private IList _drawables = new List(Constants.DRAWABLE_OBJECTS_SIZE_INITIAL); private IStateEnable _stateEnable = null!; private GameObjectFactory _gameObjectFactory = null!; private bool _initialized = false; private GameObjectFactory GameObjectFactory { get { if (_gameObjectFactory is null) _gameObjectFactory = new GameObjectFactory(); return _gameObjectFactory; } } public bool Initialized => _initialized; public IList GameObjects => _gameObjects; public IStateEnable StateEnable { get { if (_stateEnable is null) Assign(new StateEnableFactory().Instantiate(this)); return _stateEnable; } } 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 bool Initialize() { if (Initialized) return false; foreach (var gameObject in GameObjects) gameObject.Initialize(); OnInitialized?.Invoke(this); return true; } public bool Finalize() { if (!Initialized) return false; for (int i = GameObjects.Count; i >= 0; i--) GameObjects[i].Finalize(); OnFinalized?.Invoke(this); return true; } public bool Assign(IStateEnable stateEnable) { if (_stateEnable is not null) return false; _stateEnable = stateEnable; OnStateEnableAssigned?.Invoke(this); return true; } 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); } }