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 => MlemGame.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 , before is called. /// public event TimeCallback PreUpdate; /// /// An event that is invoked in , after is called. /// public event TimeCallback OnUpdate; /// /// An event that is invoked in , before is called. /// public event TimeCallback PreDraw; /// /// An event that is invoked in , after is called. /// 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) { MlemGame.instance = this; this.GraphicsDeviceManager = new GraphicsDeviceManager(this) { PreferredBackBufferWidth = windowWidth, PreferredBackBufferHeight = windowHeight, #if !FNA HardwareModeSwitch = false #endif }; this.Window.AllowUserResizing = true; this.Content.RootDirectory = "Content"; } /// /// Override this to load graphical resources required by the game. /// 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, this.InitializeDefaultUiStyle(this.SpriteBatch), this.InputHandler); this.Components.Add(this.UiSystem); this.OnLoadContent?.Invoke(this); } /// /// Called when the game should update. /// Updates the instances attached to this game. /// Override to update your game. /// /// The elapsed time since the last call to . protected sealed override void Update(GameTime gameTime) { this.PreUpdate?.Invoke(this, gameTime); CoroutineHandler.RaiseEvent(CoroutineEvents.PreUpdate); this.DoUpdate(gameTime); this.OnUpdate?.Invoke(this, gameTime); CoroutineHandler.Tick(gameTime.ElapsedGameTime.TotalSeconds); CoroutineHandler.RaiseEvent(CoroutineEvents.Update); } /// /// Called when the game should draw a frame. /// Draws the instances attached to this game. /// Override to render your game. /// /// A instance containing the elapsed time since the last call to and the total time elapsed since the game started. protected sealed override void Draw(GameTime gameTime) { this.PreDraw?.Invoke(this, gameTime); CoroutineHandler.RaiseEvent(CoroutineEvents.PreDraw); #pragma warning disable CS0618 this.UiSystem.DrawEarly(gameTime, this.SpriteBatch); #pragma warning restore CS0618 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); } /// /// This method is called in when the is initialized. /// Override this method to easily modify or create a new default for this game's . /// /// The sprite batch to use /// The to use for this game's . protected virtual UiStyle InitializeDefaultUiStyle(SpriteBatch batch) { return new UntexturedStyle(batch); } /// /// 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 MlemGame.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); } }