using Coroutine; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using MLEM.Input; using MLEM.Ui; using MLEM.Ui.Style; namespace MLEM.Startup { /// /// MlemGame is an extension of MonoGame's default class. /// It features the default template setup, as well as an , a and some additional callback events. /// It also runs all of the callbacks which can be used through . /// public class MlemGame : Game { private static MlemGame instance; /// /// The static game instance's input handler /// public static InputHandler Input => instance.InputHandler; /// /// This game's graphics device manager, initialized in the constructor /// public readonly GraphicsDeviceManager GraphicsDeviceManager; /// /// This game's sprite batch /// public SpriteBatch SpriteBatch { get; protected set; } /// /// This game's input handler. This can easily be accessed through . /// public InputHandler InputHandler { get; protected set; } /// /// This game's ui system /// public UiSystem UiSystem { get; protected set; } /// /// An event that is invoked in /// public event GenericCallback OnLoadContent; /// /// An event that is invoked in /// public event TimeCallback OnUpdate; /// /// An event that is invoked in /// public event TimeCallback OnDraw; /// /// Creates a new MlemGame instance with some default settings /// /// The default window width /// The default window height public MlemGame(int windowWidth = 1280, int windowHeight = 720) { instance = this; this.GraphicsDeviceManager = new GraphicsDeviceManager(this) { PreferredBackBufferWidth = windowWidth, PreferredBackBufferHeight = windowHeight, HardwareModeSwitch = false }; this.Window.AllowUserResizing = true; this.Content.RootDirectory = "Content"; } /// protected override void LoadContent() { this.SpriteBatch = new SpriteBatch(this.GraphicsDevice); this.InputHandler = new InputHandler(this); this.Components.Add(this.InputHandler); this.UiSystem = new UiSystem(this, new UntexturedStyle(this.SpriteBatch), this.InputHandler); this.Components.Add(this.UiSystem); this.OnLoadContent?.Invoke(this); } /// protected sealed override void Update(GameTime gameTime) { this.DoUpdate(gameTime); this.OnUpdate?.Invoke(this, gameTime); CoroutineHandler.Tick(gameTime.ElapsedGameTime.TotalSeconds); CoroutineHandler.RaiseEvent(CoroutineEvents.Update); } /// protected sealed override void Draw(GameTime gameTime) { this.UiSystem.DrawEarly(gameTime, this.SpriteBatch); this.DoDraw(gameTime); this.UiSystem.Draw(gameTime, this.SpriteBatch); this.OnDraw?.Invoke(this, gameTime); CoroutineHandler.RaiseEvent(CoroutineEvents.Draw); } /// /// This method is called in . /// It is the version that should be overridden by implementors to draw game content. /// /// The game's time protected virtual void DoDraw(GameTime gameTime) { base.Draw(gameTime); } /// /// This method is called in . /// It is the version that should be overridden by implementors to update game content. /// /// The game's time protected virtual void DoUpdate(GameTime gameTime) { base.Update(gameTime); } /// /// Static helper method for . /// This just invokes the game instance's load method. /// /// The name of the content file to load /// The type of content to load /// The loaded content public static T LoadContent(string name) { return instance.Content.Load(name); } /// /// A delegate method used by . /// /// The game in question public delegate void GenericCallback(MlemGame game); /// /// A delegate method used by and . /// /// The game in question /// The game's current time public delegate void TimeCallback(MlemGame game, GameTime time); } }