using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Media; using V3.Input; namespace V3.Screens { /// /// Default implementation of IScreenManager. /// // ReSharper disable once ClassNeverInstantiated.Global internal sealed class ScreenManager : IScreenManager { private readonly IInputManager mInputManager; private readonly DebugScreen mDebugScreen; private readonly ContentManager mContentManager; private readonly Stack mScreens = new Stack(); /// /// Creates a new screen manager using the given input manager. /// public ScreenManager(IInputManager inputManager, DebugScreen debugScreen, ContentManager contentManager) { mInputManager = inputManager; mDebugScreen = debugScreen; mContentManager = contentManager; } /// /// Adds a screen to the foreground. /// /// the screen to add in the foreground public void AddScreen(IScreen screen) { mScreens.Push(screen); #if NO_AUDIO #else if (screen is MainScreen) { MediaPlayer.IsRepeating = true; MediaPlayer.Play(mContentManager.Load("Sounds/Kosta_T_-_06")); } else if (screen is GameScreen) { MediaPlayer.IsRepeating = true; MediaPlayer.Play(mContentManager.Load("Sounds/Afraid_to_Go")); } //else if (screen is PauseScreen) //{ // mAbstractCreature.GetSelf(); // mAbstractCreature.mSoundEffectInstance.Stop(); // mAbstractCreature.mSoundEffectInstanceFight.Stop(); // mAbstractCreature.mSoundEffectInstanceHorse.Stop(); // mAbstractCreature.mSoundEffectInstanceKnight.Stop(); // mAbstractCreature.mSoundEffectInstanceMeatball.Stop(); //} #endif } /// /// Removes the given screen if it is on the top of the screen stack. /// /// the screen to remove public void RemoveScreen(IScreen screen) { if (mScreens.Count > 0 && screen.Equals(mScreens.Peek())) { mScreens.Pop(); } } /// /// Clears the screen stack. /// public void Clear() { mScreens.Clear(); } /// /// Draws the top screen and, if enabled, the lower screens. The draw /// order is from bottom to top, i. e. the lowest enabled screen is /// drawn first, and the top screen is drawn last. /// /// a snapshot of the game time /// the sprite batch to use for drawing /// public void Draw(GameTime gameTime, SpriteBatch spriteBatch) { var drawScreens = new Stack(); foreach (var screen in mScreens) { drawScreens.Push(screen); if (!screen.DrawLower) break; } foreach (var screen in drawScreens) { screen.Draw(gameTime, spriteBatch); } mDebugScreen.Draw(gameTime, spriteBatch); } /// /// Updates the top screen and, if enabled, the lower screens. The /// update order is from top to bottom, i. e. the lowest enabled screen /// is drawn first, and the top screen is drawn last. /// /// a snapshot of the game time public void Update(GameTime gameTime) { mInputManager.Update(); HandleInputEvents(); mDebugScreen.Update(gameTime); var currentScreens = new Stack(new Stack(mScreens)); foreach (var screen in currentScreens) { screen.Update(gameTime); if (!screen.UpdateLower) break; } } private void HandleInputEvents() { // We need to clone the stack as the input management methods // might want to modify the screen stack. We need two stacks as // each stack reverses the order. var currentScreens = new Stack(new Stack(mScreens)); foreach (var keyEvent in mInputManager.KeyEvents) { foreach (var screen in currentScreens) { if (screen.HandleKeyEvent(keyEvent)) break; } } foreach (var mouseEvent in mInputManager.MouseEvents) { foreach (var screen in currentScreens) { if (screen.HandleMouseEvent(mouseEvent)) break; } } } public GameScreen GetGameScreen() { foreach (var screen in mScreens) { if (screen is GameScreen) return (GameScreen) screen; } return null; } } }