Skip to content

Instantly share code, notes, and snippets.

/MainMenuScreen Secret

Created May 30, 2015 18:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anonymous/e0d085f2d6be23d1d5db to your computer and use it in GitHub Desktop.
Save anonymous/e0d085f2d6be23d1d5db to your computer and use it in GitHub Desktop.
#region File Description
//-----------------------------------------------------------------------------
// MainMenuScreen.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion
#region Using Statements
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
#endregion
namespace Rogue_Like_LOL
{
/// <summary>
/// The main menu screen is the first thing displayed when the game starts up.
/// </summary>
class MainMenuScreen : MenuScreen
{
#region Initialization
Texture2D playgame;
Texture2D exit;
public override void LoadContent()
{
base.LoadContent();
Art.LoadMenu(ScreenManager.Game.Content);
}
/// <summary>
/// Constructor fills in the menu contents.
/// </summary>
public MainMenuScreen()
: base()
{
playgame = Art.PlayGame;
exit = Art.Exit;
// Create our menu entries.
MenuEntry playGameMenuEntry = new MenuEntry(playgame);
MenuEntry exitMenuEntry = new MenuEntry(exit);
// Hook up menu event handlers.
playGameMenuEntry.Selected += PlayGameMenuEntrySelected;
exitMenuEntry.Selected += OnCancel;
// Add entries to the menu.
MenuEntries.Add(playGameMenuEntry);
MenuEntries.Add(exitMenuEntry);
}
#endregion
#region Handle Input
/// <summary>
/// Event handler for when the Play Game menu entry is selected.
/// </summary>
void PlayGameMenuEntrySelected(object sender, PlayerIndexEventArgs e)
{
LoadingScreen.Load(ScreenManager, true, e.PlayerIndex,
new GameplayScreen());
}
/// <summary>
/// When the user cancels the main menu, ask if they want to exit the sample.
/// </summary>
protected override void OnCancel(PlayerIndex playerIndex)
{
ScreenManager.Game.Exit();
}
#endregion
}
}
#region File Description
//-----------------------------------------------------------------------------
// MenuEntry.cs
//
// XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion
#region Using Statements
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
#endregion
namespace Rogue_Like_LOL
{
/// <summary>
/// Helper class represents a single entry in a MenuScreen. By default this
/// just draws the entry text string, but it can be customized to display menu
/// entries in different ways. This also provides an event that will be raised
/// when the menu entry is selected.
/// </summary>
class MenuEntry
{
#region Fields
Texture2D image;
/// <summary>
/// The text rendered for this entry.
/// </summary>
string text;
/// <summary>
/// Tracks a fading selection effect on the entry.
/// </summary>
/// <remarks>
/// The entries transition out of the selection effect when they are deselected.
/// </remarks>
float selectionFade;
/// <summary>
/// The position at which the entry is drawn. This is set by the MenuScreen
/// each frame in Update.
/// </summary>
Vector2 position;
#endregion
#region Properties
/// <summary>
/// Gets or sets the text of this menu entry.
/// </summary>
public string Text
{
get { return text; }
set { text = value; }
}
/// <summary>
/// Gets or sets the position at which to draw this menu entry.
/// </summary>
public Vector2 Position
{
get { return position; }
set { position = value; }
}
#endregion
#region Events
/// <summary>
/// Event raised when the menu entry is selected.
/// </summary>
public event EventHandler<PlayerIndexEventArgs> Selected;
/// <summary>
/// Method for raising the Selected event.
/// </summary>
protected internal virtual void OnSelectEntry(PlayerIndex playerIndex)
{
if (Selected != null)
Selected(this, new PlayerIndexEventArgs(playerIndex));
}
#endregion
#region Initialization
/// <summary>
/// Constructs a new menu entry with the specified text.
/// </summary>
public MenuEntry(Texture2D tex)
{
image = tex;
}
#endregion
#region Update and Draw
/// <summary>
/// Updates the menu entry.
/// </summary>
public virtual void Update(MenuScreen screen, bool isSelected, GameTime gameTime)
{
// there is no such thing as a selected item on Windows Phone, so we always
// force isSelected to be false
#if WINDOWS_PHONE
isSelected = false;
#endif
// When the menu selection changes, entries gradually fade between
// their selected and deselected appearance, rather than instantly
// popping to the new state.
float fadeSpeed = (float)gameTime.ElapsedGameTime.TotalSeconds * 4;
if (isSelected)
selectionFade = Math.Min(selectionFade + fadeSpeed, 1);
else
selectionFade = Math.Max(selectionFade - fadeSpeed, 0);
}
/// <summary>
/// Draws the menu entry. This can be overridden to customize the appearance.
/// </summary>
public virtual void Draw(MenuScreen screen, bool isSelected, GameTime gameTime)
{
// there is no such thing as a selected item on Windows Phone, so we always
// force isSelected to be false
#if WINDOWS_PHONE
isSelected = false;
#endif
// Draw the selected entry in yellow, otherwise white.
Color color = isSelected ? Color.Yellow : Color.White;
// Pulsate the size of the selected menu entry.
/*double time = gameTime.TotalGameTime.TotalSeconds;
float pulsate = (float)Math.Sin(time * 6) + 1;
float scale = 1 + pulsate * 0.05f * selectionFade;*/
// Modify the alpha to fade text out during transitions.
color *= screen.TransitionAlpha;
// Draw text, centered on the middle of each line.
ScreenManager screenManager = screen.ScreenManager;
SpriteBatch spriteBatch = screenManager.SpriteBatch;
SpriteFont font = screenManager.Font;
//Vector2 origin = new Vector2(0, font.LineSpacing / 2);
/*spriteBatch.DrawString(font, text, position, color, 0,
origin, 1f, SpriteEffects.None, 0);*/
spriteBatch.Draw(image, position / 2, color);
}
/// <summary>
/// Queries how much space this menu entry requires.
/// </summary>
public virtual int GetHeight(MenuScreen screen)
{
return this.image.Height;
}
/// <summary>
/// Queries how wide the entry is, used for centering on the screen.
/// </summary>
public virtual int GetWidth(MenuScreen screen)
{
return this.image.Width;
}
#endregion
}
}
#region File Description
//-----------------------------------------------------------------------------
// MenuScreen.cs
//
// XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion
#region Using Statements
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework.Input;
#endregion
namespace Rogue_Like_LOL
{
/// <summary>
/// Base class for screens that contain a menu of options. The user can
/// move up and down to select an entry, or cancel to back out of the screen.
/// </summary>
abstract class MenuScreen : GameScreen
{
#region Fields
List<MenuEntry> menuEntries = new List<MenuEntry>();
int selectedEntry = 0;
#endregion
#region Properties
/// <summary>
/// Gets the list of menu entries, so derived classes can add
/// or change the menu contents.
/// </summary>
protected IList<MenuEntry> MenuEntries
{
get { return menuEntries; }
}
#endregion
#region Initialization
/// <summary>
/// Constructor.
/// </summary>
public MenuScreen()
{
TransitionOnTime = TimeSpan.FromSeconds(0.5);
TransitionOffTime = TimeSpan.FromSeconds(0.5);
}
#endregion
#region Handle Input
/// <summary>
/// Responds to user input, changing the selected entry and accepting
/// or cancelling the menu.
/// </summary>
public override void HandleInput(InputState input)
{
// Move to the previous menu entry?
if (input.IsMenuUp(ControllingPlayer))
{
selectedEntry--;
if (selectedEntry < 0)
selectedEntry = menuEntries.Count - 1;
}
// Move to the next menu entry?
if (input.IsMenuDown(ControllingPlayer))
{
selectedEntry++;
if (selectedEntry >= menuEntries.Count)
selectedEntry = 0;
}
// Accept or cancel the menu? We pass in our ControllingPlayer, which may
// either be null (to accept input from any player) or a specific index.
// If we pass a null controlling player, the InputState helper returns to
// us which player actually provided the input. We pass that through to
// OnSelectEntry and OnCancel, so they can tell which player triggered them.
PlayerIndex playerIndex;
if (input.IsMenuSelect(ControllingPlayer, out playerIndex))
{
OnSelectEntry(selectedEntry, playerIndex);
}
else if (input.IsMenuCancel(ControllingPlayer, out playerIndex))
{
OnCancel(playerIndex);
}
}
/// <summary>
/// Handler for when the user has chosen a menu entry.
/// </summary>
protected virtual void OnSelectEntry(int entryIndex, PlayerIndex playerIndex)
{
menuEntries[entryIndex].OnSelectEntry(playerIndex);
}
/// <summary>
/// Handler for when the user has cancelled the menu.
/// </summary>
protected virtual void OnCancel(PlayerIndex playerIndex)
{
ExitScreen();
}
/// <summary>
/// Helper overload makes it easy to use OnCancel as a MenuEntry event handler.
/// </summary>
protected void OnCancel(object sender, PlayerIndexEventArgs e)
{
OnCancel(e.PlayerIndex);
}
#endregion
#region Update and Draw
/// <summary>
/// Allows the screen the chance to position the menu entries. By default
/// all menu entries are lined up in a vertical list, centered on the screen.
/// </summary>
protected virtual void UpdateMenuEntryLocations()
{
// Make the menu slide into place during transitions, using a
// power curve to make things look more interesting (this makes
// the movement slow down as it nears the end).
float transitionOffset = (float)Math.Pow(TransitionPosition, 2);
// start at Y = 175; each X value is generated per entry
Vector2 position = new Vector2(0f, 500f);
// update each menu entry's location in turn
for (int i = 0; i < menuEntries.Count; i++)
{
MenuEntry menuEntry = menuEntries[i];
// each entry is to be centered horizontally
position.X = ScreenManager.GraphicsDevice.Viewport.Width / 2 - menuEntry.GetWidth(this) / 2;
if (ScreenState == ScreenState.TransitionOn)
position.X -= transitionOffset * 256;
else
position.X += transitionOffset * 512;
// set the entry's position
menuEntry.Position = position;
// move down for the next entry the size of this entry
position.Y += menuEntry.GetHeight(this) + 10;
}
}
/// <summary>
/// Updates the menu.
/// </summary>
public override void Update(GameTime gameTime, bool otherScreenHasFocus,
bool coveredByOtherScreen)
{
base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
// Update each nested MenuEntry object.
for (int i = 0; i < menuEntries.Count; i++)
{
bool isSelected = IsActive && (i == selectedEntry);
menuEntries[i].Update(this, isSelected, gameTime);
}
}
/// <summary>
/// Draws the menu.
/// </summary>
public override void Draw(GameTime gameTime)
{
// make sure our entries are in the right place before we draw them
UpdateMenuEntryLocations();
GraphicsDevice graphics = ScreenManager.GraphicsDevice;
SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
spriteBatch.Begin();
// Draw each menu entry in turn.
for (int i = 0; i < menuEntries.Count; i++)
{
MenuEntry menuEntry = menuEntries[i];
bool isSelected = IsActive && (i == selectedEntry);
menuEntry.Draw(this, isSelected, gameTime);
}
// Make the menu slide into place during transitions, using a
// power curve to make things look more interesting (this makes
// the movement slow down as it nears the end).
// float transitionOffset = (float)Math.Pow(TransitionPosition, 4);
spriteBatch.End();
}
#endregion
}
}
#region File Description
//-----------------------------------------------------------------------------
// ScreenManager.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion
#region Using Statements
using System;
using System.Diagnostics;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input.Touch;
#endregion
namespace Rogue_Like_LOL
{
/// <summary>
/// The screen manager is a component which manages one or more GameScreen
/// instances. It maintains a stack of screens, calls their Update and Draw
/// methods at the appropriate times, and automatically routes input to the
/// topmost active screen.
/// </summary>
public class ScreenManager : DrawableGameComponent
{
#region Fields
List<GameScreen> screens = new List<GameScreen>();
List<GameScreen> screensToUpdate = new List<GameScreen>();
InputState input = new InputState();
SpriteBatch spriteBatch;
SpriteFont font;
Texture2D blankTexture;
bool isInitialized;
bool traceEnabled;
#endregion
#region Properties
/// <summary>
/// A default SpriteBatch shared by all the screens. This saves
/// each screen having to bother creating their own local instance.
/// </summary>
public SpriteBatch SpriteBatch
{
get { return spriteBatch; }
}
/// <summary>
/// A default font shared by all the screens. This saves
/// each screen having to bother loading their own local copy.
/// </summary>
public SpriteFont Font
{
get { return font; }
}
/// <summary>
/// If true, the manager prints out a list of all the screens
/// each time it is updated. This can be useful for making sure
/// everything is being added and removed at the right times.
/// </summary>
public bool TraceEnabled
{
get { return traceEnabled; }
set { traceEnabled = value; }
}
#endregion
#region Initialization
/// <summary>
/// Constructs a new screen manager component.
/// </summary>
public ScreenManager(Game game)
: base(game)
{
// we must set EnabledGestures before we can query for them, but
// we don't assume the game wants to read them.
TouchPanel.EnabledGestures = GestureType.None;
}
/// <summary>
/// Initializes the screen manager component.
/// </summary>
public override void Initialize()
{
base.Initialize();
isInitialized = true;
}
/// <summary>
/// Load your graphics content.
/// </summary>
protected override void LoadContent()
{
// Load content belonging to the screen manager.
ContentManager content = Game.Content;
spriteBatch = new SpriteBatch(GraphicsDevice);
font = content.Load<SpriteFont>("Font");
blankTexture = content.Load<Texture2D>("blank");
// Tell each of the screens to load their content.
foreach (GameScreen screen in screens)
{
screen.LoadContent();
}
}
/// <summary>
/// Unload your graphics content.
/// </summary>
protected override void UnloadContent()
{
// Tell each of the screens to unload their content.
foreach (GameScreen screen in screens)
{
screen.UnloadContent();
}
}
#endregion
#region Update and Draw
/// <summary>
/// Allows each screen to run logic.
/// </summary>
public override void Update(GameTime gameTime)
{
// Read the keyboard and gamepad.
input.Update();
// Make a copy of the master screen list, to avoid confusion if
// the process of updating one screen adds or removes others.
screensToUpdate.Clear();
foreach (GameScreen screen in screens)
screensToUpdate.Add(screen);
bool otherScreenHasFocus = !Game.IsActive;
bool coveredByOtherScreen = false;
// Loop as long as there are screens waiting to be updated.
while (screensToUpdate.Count > 0)
{
// Pop the topmost screen off the waiting list.
GameScreen screen = screensToUpdate[screensToUpdate.Count - 1];
screensToUpdate.RemoveAt(screensToUpdate.Count - 1);
// Update the screen.
screen.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
if (screen.ScreenState == ScreenState.TransitionOn ||
screen.ScreenState == ScreenState.Active)
{
// If this is the first active screen we came across,
// give it a chance to handle input.
if (!otherScreenHasFocus)
{
screen.HandleInput(input);
otherScreenHasFocus = true;
}
// If this is an active non-popup, inform any subsequent
// screens that they are covered by it.
if (!screen.IsPopup)
coveredByOtherScreen = true;
}
}
// Print debug trace?
if (traceEnabled)
TraceScreens();
}
/// <summary>
/// Prints a list of all the screens, for debugging.
/// </summary>
void TraceScreens()
{
List<string> screenNames = new List<string>();
foreach (GameScreen screen in screens)
screenNames.Add(screen.GetType().Name);
Debug.WriteLine(string.Join(", ", screenNames.ToArray()));
}
/// <summary>
/// Tells each screen to draw itself.
/// </summary>
public override void Draw(GameTime gameTime)
{
foreach (GameScreen screen in screens)
{
if (screen.ScreenState == ScreenState.Hidden)
continue;
screen.Draw(gameTime);
}
}
#endregion
#region Public Methods
/// <summary>
/// Adds a new screen to the screen manager.
/// </summary>
public void AddScreen(GameScreen screen, PlayerIndex? controllingPlayer)
{screen.ControllingPlayer = controllingPlayer;
screen.ScreenManager = this;
screen.IsExiting = false;
// If we have a graphics device, tell the screen to load content.
if (isInitialized)
{
screen.LoadContent();
}
screens.Add(screen);
// update the TouchPanel to respond to gestures this screen is interested in
}
/// <summary>
/// Removes a screen from the screen manager. You should normally
/// use GameScreen.ExitScreen instead of calling this directly, so
/// the screen can gradually transition off rather than just being
/// instantly removed.
/// </summary>
public void RemoveScreen(GameScreen screen)
{
// If we have a graphics device, tell the screen to unload content.
if (isInitialized)
{
screen.UnloadContent();
}
screens.Remove(screen);
screensToUpdate.Remove(screen);
// if there is a screen still in the manager, update TouchPanel
// to respond to gestures that screen is interested in.
if (screens.Count > 0)
{
TouchPanel.EnabledGestures = screens[screens.Count - 1].EnabledGestures;
}
}
/// <summary>
/// Expose an array holding all the screens. We return a copy rather
/// than the real master list, because screens should only ever be added
/// or removed using the AddScreen and RemoveScreen methods.
/// </summary>
public GameScreen[] GetScreens()
{
return screens.ToArray();
}
/// <summary>
/// Helper draws a translucent black fullscreen sprite, used for fading
/// screens in and out, and for darkening the background behind popups.
/// </summary>
public void FadeBackBufferToBlack(float alpha)
{
Viewport viewport = GraphicsDevice.Viewport;
spriteBatch.Begin();
spriteBatch.Draw(blankTexture,
new Rectangle(0, 0, viewport.Width, viewport.Height),
Color.Black * alpha);
spriteBatch.End();
}
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment