diff --git a/axios/Axios_WP7.csproj b/axios/Axios_WP7.csproj
index 45f9c86..d5658bf 100644
--- a/axios/Axios_WP7.csproj
+++ b/axios/Axios_WP7.csproj
@@ -190,18 +190,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/axios/Axios_Windows.csproj b/axios/Axios_Windows.csproj
index 1b76ffe..2c73e8c 100644
--- a/axios/Axios_Windows.csproj
+++ b/axios/Axios_Windows.csproj
@@ -234,19 +234,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/axios/Axios_Windows.csproj.user b/axios/Axios_Windows.csproj.user
index 76fe5a5..566c009 100644
--- a/axios/Axios_Windows.csproj.user
+++ b/axios/Axios_Windows.csproj.user
@@ -1,6 +1,6 @@
- ProjectFiles
+ ShowAllFiles
\ No newline at end of file
diff --git a/axios/Axios_Xbox_360.csproj b/axios/Axios_Xbox_360.csproj
index f15b1d4..7c073c9 100644
--- a/axios/Axios_Xbox_360.csproj
+++ b/axios/Axios_Xbox_360.csproj
@@ -183,18 +183,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/axios/Engine/AxiosGameScreen.cs b/axios/Engine/AxiosGameScreen.cs
index ece11f8..a487746 100644
--- a/axios/Engine/AxiosGameScreen.cs
+++ b/axios/Engine/AxiosGameScreen.cs
@@ -8,7 +8,9 @@ using Axios.Engine.UI;
using FarseerPhysics.Dynamics;
using FarseerPhysics.SamplesFramework;
using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
+using GameStateManagement;
namespace Axios.Engine
{
@@ -158,19 +160,16 @@ namespace Axios.Engine
AxiosLog.Instance.AddLine("Memory usage after cleanup: ", LoggingFlag.DEBUG);
}
- public override void ExitScreen()
+ public override void Activate(bool instancePreserved)
{
- base.ExitScreen();
-
- }
-
- public override void LoadContent()
- {
- base.LoadContent();
+ base.Activate(instancePreserved);
#if DEBUG
if (!Axios.Settings.ScreenSaver)
- this.DebugSpriteFont = this.ScreenManager.Content.Load(this.DebugTextFont);
+ {
+ ContentManager man = new ContentManager(ScreenManager.Game.Services, "Content");
+ this.DebugSpriteFont = man.Load(this.DebugTextFont);
+ }
#endif
}
diff --git a/axios/ScreenSystem/BackgroundScreen.cs b/axios/ScreenSystem/BackgroundScreen.cs
index f4903a6..e3df4d5 100644
--- a/axios/ScreenSystem/BackgroundScreen.cs
+++ b/axios/ScreenSystem/BackgroundScreen.cs
@@ -1,24 +1,38 @@
-using System;
-using Microsoft.Xna.Framework;
-using Microsoft.Xna.Framework.Graphics;
+#region File Description
+//-----------------------------------------------------------------------------
+// BackgroundScreen.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
-namespace FarseerPhysics.SamplesFramework
+#region Using Statements
+using System;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Content;
+using Microsoft.Xna.Framework.Graphics;
+using GameStateManagement;
+#endregion
+
+namespace GameStateManagement
{
///
/// The background screen sits behind all the other menu screens.
/// It draws a background image that remains fixed in place regardless
/// of whatever transitions the screens on top of it may be doing.
///
- public class BackgroundScreen : GameScreen
+ class BackgroundScreen : GameScreen
{
- private const float LogoScreenHeightRatio = 0.25f;
- private const float LogoScreenBorderRatio = 0.0375f;
- private const float LogoWidthHeightRatio = 1.4f;
+ #region Fields
+
+ ContentManager content;
+ Texture2D backgroundTexture;
+
+ #endregion
+
+ #region Initialization
- private Texture2D _backgroundTexture;
- private Rectangle _logoDestination;
- //private Texture2D _logoTexture;
- private Rectangle _viewport;
///
/// Constructor.
@@ -29,24 +43,40 @@ namespace FarseerPhysics.SamplesFramework
TransitionOffTime = TimeSpan.FromSeconds(0.5);
}
- public override void LoadContent()
+
+ ///
+ /// Loads graphics content for this screen. The background texture is quite
+ /// big, so we use our own local ContentManager to load it. This allows us
+ /// to unload before going from the menus into the game itself, wheras if we
+ /// used the shared ContentManager provided by the Game class, the content
+ /// would remain loaded forever.
+ ///
+ public override void Activate(bool instancePreserved)
{
- //_logoTexture = ScreenManager.Content.Load("Common/logo");
- _backgroundTexture = ScreenManager.Content.Load("Common/gradient");
+ if (!instancePreserved)
+ {
+ if (content == null)
+ content = new ContentManager(ScreenManager.Game.Services, "Content");
- Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
- Vector2 logoSize = new Vector2();
- logoSize.Y = viewport.Height * LogoScreenHeightRatio;
- logoSize.X = logoSize.Y * LogoWidthHeightRatio;
-
- float border = viewport.Height * LogoScreenBorderRatio;
- Vector2 logoPosition = new Vector2(viewport.Width - border - logoSize.X,
- viewport.Height - border - logoSize.Y);
- _logoDestination = new Rectangle((int)logoPosition.X, (int)logoPosition.Y, (int)logoSize.X,
- (int)logoSize.Y);
- _viewport = viewport.Bounds;
+ backgroundTexture = content.Load("background");
+ }
}
+
+ ///
+ /// Unloads graphics content for this screen.
+ ///
+ public override void Unload()
+ {
+ content.Unload();
+ }
+
+
+ #endregion
+
+ #region Update and Draw
+
+
///
/// Updates the background screen. Unlike most screens, this should not
/// transition off even if it has been covered by another screen: it is
@@ -55,20 +85,30 @@ namespace FarseerPhysics.SamplesFramework
/// Update method wanting to transition off.
///
public override void Update(GameTime gameTime, bool otherScreenHasFocus,
- bool coveredByOtherScreen)
+ bool coveredByOtherScreen)
{
base.Update(gameTime, otherScreenHasFocus, false);
}
+
///
/// Draws the background screen.
///
public override void Draw(GameTime gameTime)
{
- ScreenManager.SpriteBatch.Begin();
- ScreenManager.SpriteBatch.Draw(_backgroundTexture, _viewport, Color.White);
- //ScreenManager.SpriteBatch.Draw(_logoTexture, _logoDestination, Color.White * 0.6f);
- ScreenManager.SpriteBatch.End();
+ SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
+ Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
+ Rectangle fullscreen = new Rectangle(0, 0, viewport.Width, viewport.Height);
+
+ spriteBatch.Begin();
+
+ spriteBatch.Draw(backgroundTexture, fullscreen,
+ new Color(TransitionAlpha, TransitionAlpha, TransitionAlpha));
+
+ spriteBatch.End();
}
+
+
+ #endregion
}
-}
\ No newline at end of file
+}
diff --git a/axios/ScreenSystem/FramerateCounterComponent.cs b/axios/ScreenSystem/FramerateCounterComponent.cs
index da8b0a0..cf8803e 100644
--- a/axios/ScreenSystem/FramerateCounterComponent.cs
+++ b/axios/ScreenSystem/FramerateCounterComponent.cs
@@ -1,6 +1,7 @@
using System;
using System.Globalization;
using Microsoft.Xna.Framework;
+using GameStateManagement;
namespace FarseerPhysics.SamplesFramework
{
diff --git a/axios/ScreenSystem/GameScreen.cs b/axios/ScreenSystem/GameScreen.cs
index 68281cc..5319df2 100644
--- a/axios/ScreenSystem/GameScreen.cs
+++ b/axios/ScreenSystem/GameScreen.cs
@@ -1,19 +1,18 @@
#region File Description
-
//-----------------------------------------------------------------------------
-// PlayerIndexEventArgs.cs
+// GameScreen.cs
//
-// XNA Community Game Platform
+// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
-
#endregion
using System;
+using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input.Touch;
-namespace FarseerPhysics.SamplesFramework
+namespace GameStateManagement
{
///
/// Enum describes the screen transition state.
@@ -26,6 +25,7 @@ namespace FarseerPhysics.SamplesFramework
Hidden,
}
+
///
/// A screen is a single layer that has update and draw logic, and which
/// can be combined with other layers to build up a complex menu system.
@@ -35,23 +35,6 @@ namespace FarseerPhysics.SamplesFramework
///
public abstract class GameScreen
{
- private GestureType _enabledGestures = GestureType.None;
- private bool _otherScreenHasFocus;
-
- public GameScreen()
- {
- ScreenState = ScreenState.TransitionOn;
- TransitionPosition = 1;
- TransitionOffTime = TimeSpan.Zero;
- TransitionOnTime = TimeSpan.Zero;
- HasCursor = false;
- HasVirtualStick = false;
- }
-
- public bool HasCursor { get; set; }
-
- public bool HasVirtualStick { get; set; }
-
///
/// Normally when one screen is brought up over the top of another,
/// the first screen will transition off to make room for the new
@@ -59,26 +42,54 @@ namespace FarseerPhysics.SamplesFramework
/// popup, in which case screens underneath it do not need to bother
/// transitioning off.
///
- public bool IsPopup { get; protected set; }
+ public bool IsPopup
+ {
+ get { return isPopup; }
+ protected set { isPopup = value; }
+ }
+
+ bool isPopup = false;
+
///
/// Indicates how long the screen takes to
/// transition on when it is activated.
///
- public TimeSpan TransitionOnTime { get; protected set; }
+ public TimeSpan TransitionOnTime
+ {
+ get { return transitionOnTime; }
+ protected set { transitionOnTime = value; }
+ }
+
+ TimeSpan transitionOnTime = TimeSpan.Zero;
+
///
/// Indicates how long the screen takes to
/// transition off when it is deactivated.
///
- public TimeSpan TransitionOffTime { get; protected set; }
+ public TimeSpan TransitionOffTime
+ {
+ get { return transitionOffTime; }
+ protected set { transitionOffTime = value; }
+ }
+
+ TimeSpan transitionOffTime = TimeSpan.Zero;
+
///
/// Gets the current position of the screen transition, ranging
/// from zero (fully active, no transition) to one (transitioned
/// fully off to nothing).
///
- public float TransitionPosition { get; protected set; }
+ public float TransitionPosition
+ {
+ get { return transitionPosition; }
+ protected set { transitionPosition = value; }
+ }
+
+ float transitionPosition = 1;
+
///
/// Gets the current alpha of the screen transition, ranging
@@ -90,10 +101,18 @@ namespace FarseerPhysics.SamplesFramework
get { return 1f - TransitionPosition; }
}
+
///
/// Gets the current screen transition state.
///
- public ScreenState ScreenState { get; protected set; }
+ public ScreenState ScreenState
+ {
+ get { return screenState; }
+ protected set { screenState = value; }
+ }
+
+ ScreenState screenState = ScreenState.TransitionOn;
+
///
/// There are two possible reasons why a screen might be transitioning
@@ -103,9 +122,14 @@ namespace FarseerPhysics.SamplesFramework
/// if set, the screen will automatically remove itself as soon as the
/// transition finishes.
///
- public bool IsExiting { get; protected internal set; }
+ public bool IsExiting
+ {
+ get { return isExiting; }
+ protected internal set { isExiting = value; }
+ }
+
+ bool isExiting = false;
- public bool AlwaysHasFocus = false;
///
/// Checks whether this screen is active and can respond to user input.
@@ -114,16 +138,43 @@ namespace FarseerPhysics.SamplesFramework
{
get
{
- return !_otherScreenHasFocus &&
- (ScreenState == ScreenState.TransitionOn ||
- ScreenState == ScreenState.Active);
+ return !otherScreenHasFocus &&
+ (screenState == ScreenState.TransitionOn ||
+ screenState == ScreenState.Active);
}
}
+ bool otherScreenHasFocus;
+
+
///
/// Gets the manager that this screen belongs to.
///
- public ScreenManager ScreenManager { get; internal set; }
+ public ScreenManager ScreenManager
+ {
+ get { return screenManager; }
+ internal set { screenManager = value; }
+ }
+
+ ScreenManager screenManager;
+
+
+ ///
+ /// Gets the index of the player who is currently controlling this screen,
+ /// or null if it is accepting input from any player. This is used to lock
+ /// the game to a specific player profile. The main menu responds to input
+ /// from any connected gamepad, but whichever player makes a selection from
+ /// this menu is given control over all subsequent screens, so other gamepads
+ /// are inactive until the controlling player returns to the main menu.
+ ///
+ public PlayerIndex? ControllingPlayer
+ {
+ get { return controllingPlayer; }
+ internal set { controllingPlayer = value; }
+ }
+
+ PlayerIndex? controllingPlayer;
+
///
/// Gets the gestures the screen is interested in. Screens should be as specific
@@ -134,10 +185,10 @@ namespace FarseerPhysics.SamplesFramework
///
public GestureType EnabledGestures
{
- get { return _enabledGestures; }
+ get { return enabledGestures; }
protected set
{
- _enabledGestures = value;
+ enabledGestures = value;
// the screen manager handles this during screen changes, but
// if this screen is active and the gesture types are changing,
@@ -149,36 +200,62 @@ namespace FarseerPhysics.SamplesFramework
}
}
- ///
- /// Load graphics content for the screen.
- ///
- public virtual void LoadContent()
- {
- }
+ GestureType enabledGestures = GestureType.None;
///
- /// Unload content for the screen.
+ /// Gets whether or not this screen is serializable. If this is true,
+ /// the screen will be recorded into the screen manager's state and
+ /// its Serialize and Deserialize methods will be called as appropriate.
+ /// If this is false, the screen will be ignored during serialization.
+ /// By default, all screens are assumed to be serializable.
///
- public virtual void UnloadContent()
+ public bool IsSerializable
{
+ get { return isSerializable; }
+ protected set { isSerializable = value; }
}
+ bool isSerializable = true;
+
+
+ ///
+ /// Activates the screen. Called when the screen is added to the screen manager or if the game resumes
+ /// from being paused or tombstoned.
+ ///
+ ///
+ /// True if the game was preserved during deactivation, false if the screen is just being added or if the game was tombstoned.
+ /// On Xbox and Windows this will always be false.
+ ///
+ public virtual void Activate(bool instancePreserved) { }
+
+
+ ///
+ /// Deactivates the screen. Called when the game is being deactivated due to pausing or tombstoning.
+ ///
+ public virtual void Deactivate() { }
+
+
+ ///
+ /// Unload content for the screen. Called when the screen is removed from the screen manager.
+ ///
+ public virtual void Unload() { }
+
+
///
/// Allows the screen to run logic, such as updating the transition position.
/// Unlike HandleInput, this method is called regardless of whether the screen
/// is active, hidden, or in the middle of a transition.
///
- public virtual void Update(GameTime gameTime, bool otherScreenHasFocus,
- bool coveredByOtherScreen)
+ public virtual void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen)
{
- _otherScreenHasFocus = otherScreenHasFocus;
+ this.otherScreenHasFocus = otherScreenHasFocus;
- if (IsExiting)
+ if (isExiting)
{
// If the screen is going away to die, it should transition off.
- ScreenState = ScreenState.TransitionOff;
+ screenState = ScreenState.TransitionOff;
- if (!UpdateTransition(gameTime, TransitionOffTime, 1))
+ if (!UpdateTransition(gameTime, transitionOffTime, 1))
{
// When the transition finishes, remove the screen.
ScreenManager.RemoveScreen(this);
@@ -187,59 +264,55 @@ namespace FarseerPhysics.SamplesFramework
else if (coveredByOtherScreen)
{
// If the screen is covered by another, it should transition off.
- if (UpdateTransition(gameTime, TransitionOffTime, 1))
+ if (UpdateTransition(gameTime, transitionOffTime, 1))
{
// Still busy transitioning.
- ScreenState = ScreenState.TransitionOff;
+ screenState = ScreenState.TransitionOff;
}
else
{
// Transition finished!
- ScreenState = ScreenState.Hidden;
+ screenState = ScreenState.Hidden;
}
}
else
{
// Otherwise the screen should transition on and become active.
- if (UpdateTransition(gameTime, TransitionOnTime, -1))
+ if (UpdateTransition(gameTime, transitionOnTime, -1))
{
// Still busy transitioning.
- ScreenState = ScreenState.TransitionOn;
+ screenState = ScreenState.TransitionOn;
}
else
{
// Transition finished!
- ScreenState = ScreenState.Active;
+ screenState = ScreenState.Active;
}
}
}
+
///
/// Helper for updating the screen transition position.
///
- private bool UpdateTransition(GameTime gameTime, TimeSpan time, int direction)
+ bool UpdateTransition(GameTime gameTime, TimeSpan time, int direction)
{
// How much should we move by?
float transitionDelta;
if (time == TimeSpan.Zero)
- {
- transitionDelta = 1f;
- }
+ transitionDelta = 1;
else
- {
- transitionDelta = (float)(gameTime.ElapsedGameTime.TotalMilliseconds /
- time.TotalMilliseconds);
- }
+ transitionDelta = (float)(gameTime.ElapsedGameTime.TotalMilliseconds / time.TotalMilliseconds);
// Update the transition position.
- TransitionPosition += transitionDelta * direction;
+ transitionPosition += transitionDelta * direction;
// Did we reach the end of the transition?
- if (((direction < 0) && (TransitionPosition <= 0)) ||
- ((direction > 0) && (TransitionPosition >= 1)))
+ if (((direction < 0) && (transitionPosition <= 0)) ||
+ ((direction > 0) && (transitionPosition >= 1)))
{
- TransitionPosition = MathHelper.Clamp(TransitionPosition, 0, 1);
+ transitionPosition = MathHelper.Clamp(transitionPosition, 0, 1);
return false;
}
@@ -247,30 +320,29 @@ namespace FarseerPhysics.SamplesFramework
return true;
}
+
///
/// Allows the screen to handle user input. Unlike Update, this method
/// is only called when the screen is active, and not when some other
/// screen has taken the focus.
///
- public virtual void HandleInput(InputHelper input, GameTime gameTime)
- {
- }
+ public virtual void HandleInput(GameTime gameTime, InputState input) { }
+
///
/// This is called when the screen should draw itself.
///
- public virtual void Draw(GameTime gameTime)
- {
- }
+ public virtual void Draw(GameTime gameTime) { }
+
///
/// Tells the screen to go away. Unlike ScreenManager.RemoveScreen, which
/// instantly kills the screen, this method respects the transition timings
/// and will give the screen a chance to gradually transition off.
///
- public virtual void ExitScreen()
+ public void ExitScreen()
{
- if (TransitionOffTime == TimeSpan.Zero && this.TransitionPosition == 0 && this.TransitionAlpha == 1)
+ if (TransitionOffTime == TimeSpan.Zero)
{
// If the screen has a zero transition time, remove it immediately.
ScreenManager.RemoveScreen(this);
@@ -278,8 +350,8 @@ namespace FarseerPhysics.SamplesFramework
else
{
// Otherwise flag that it should transition off and then exit.
- IsExiting = true;
+ isExiting = true;
}
}
}
-}
\ No newline at end of file
+}
diff --git a/axios/ScreenSystem/InputHelper.cs b/axios/ScreenSystem/InputHelper.cs
index c3d4e1c..0703add 100644
--- a/axios/ScreenSystem/InputHelper.cs
+++ b/axios/ScreenSystem/InputHelper.cs
@@ -3,6 +3,7 @@ using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
+using GameStateManagement;
namespace FarseerPhysics.SamplesFramework
{
diff --git a/axios/ScreenSystem/LogoScreen.cs b/axios/ScreenSystem/LogoScreen.cs
index f78f3ec..27b1ed6 100644
--- a/axios/ScreenSystem/LogoScreen.cs
+++ b/axios/ScreenSystem/LogoScreen.cs
@@ -3,8 +3,9 @@ using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
+using FarseerPhysics.SamplesFramework;
-namespace FarseerPhysics.SamplesFramework
+namespace GameStateManagement
{
public class LogoScreen : GameScreen
{
@@ -29,34 +30,38 @@ namespace FarseerPhysics.SamplesFramework
/// used the shared ContentManager provided by the Game class, the content
/// would remain loaded forever.
///
- public override void LoadContent()
+ public override void Activate(bool instancePreserved)
{
- if (_content == null)
+ if (!instancePreserved)
{
- _content = new ContentManager(ScreenManager.Game.Services, "Content");
+ if (_content == null)
+ {
+ _content = new ContentManager(ScreenManager.Game.Services, "Content");
+ }
+
+ _farseerLogoTexture = _content.Load("Common/logo");
+
+ Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
+ int rectHeight = (int)(viewport.Height * LogoScreenHeightRatio);
+ int rectWidth = (int)(rectHeight * LogoWidthHeightRatio);
+ int posX = viewport.Bounds.Center.X - rectWidth / 2;
+ int posY = viewport.Bounds.Center.Y - rectHeight / 2;
+
+ _destination = new Rectangle(posX, posY, rectWidth, rectHeight);
}
-
- _farseerLogoTexture = _content.Load("Common/logo");
-
- Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
- int rectHeight = (int)(viewport.Height * LogoScreenHeightRatio);
- int rectWidth = (int)(rectHeight * LogoWidthHeightRatio);
- int posX = viewport.Bounds.Center.X - rectWidth / 2;
- int posY = viewport.Bounds.Center.Y - rectHeight / 2;
-
- _destination = new Rectangle(posX, posY, rectWidth, rectHeight);
}
///
/// Unloads graphics content for this screen.
///
- public override void UnloadContent()
+ public override void Unload()
{
_content.Unload();
}
- public override void HandleInput(InputHelper input, GameTime gameTime)
+ public override void HandleInput(GameTime gameTime, InputState input)
{
+ //input.
if (input.KeyboardState.GetPressedKeys().Length > 0 ||
input.GamePadState.IsButtonDown(Buttons.A | Buttons.Start | Buttons.Back) ||
input.MouseState.LeftButton == ButtonState.Pressed)
diff --git a/axios/ScreenSystem/MenuButton.cs b/axios/ScreenSystem/MenuButton.cs
index 67e8df4..01d5bbe 100644
--- a/axios/ScreenSystem/MenuButton.cs
+++ b/axios/ScreenSystem/MenuButton.cs
@@ -2,7 +2,7 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
-namespace FarseerPhysics.SamplesFramework
+namespace GameStateManagement
{
///
/// Helper class represents a single entry in a MenuScreen. By default this
diff --git a/axios/ScreenSystem/MenuEntry.cs b/axios/ScreenSystem/MenuEntry.cs
index 1f3efc2..6261fc1 100644
--- a/axios/ScreenSystem/MenuEntry.cs
+++ b/axios/ScreenSystem/MenuEntry.cs
@@ -1,39 +1,35 @@
-using System;
+#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.Graphics;
+using GameStateManagement;
+#endregion
-namespace FarseerPhysics.SamplesFramework
+namespace GameStateManagement
{
- public enum EntryType
- {
- Screen,
- Separator,
- ExitItem,
- BackItem
- }
-
///
/// 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.
///
- public sealed class MenuEntry
+ class MenuEntry
{
- private float _alpha;
- private Vector2 _baseOrigin;
-
- private float _height;
- private MenuScreen _menu;
+ #region Fields
///
- /// The position at which the entry is drawn. This is set by the MenuScreen
- /// each frame in Update.
+ /// The text rendered for this entry.
///
- private Vector2 _position;
-
- private float _scale;
- private GameScreen _screen;
+ string text;
///
/// Tracks a fading selection effect on the entry.
@@ -41,28 +37,17 @@ namespace FarseerPhysics.SamplesFramework
///
/// The entries transition out of the selection effect when they are deselected.
///
- private float _selectionFade;
+ float selectionFade;
///
- /// The text rendered for this entry.
+ /// The position at which the entry is drawn. This is set by the MenuScreen
+ /// each frame in Update.
///
- private string _text;
+ Vector2 position;
- private EntryType _type;
- private float _width;
+ #endregion
- ///
- /// Constructs a new menu entry with the specified text.
- ///
- public MenuEntry(MenuScreen menu, string text, EntryType type, GameScreen screen)
- {
- _text = text;
- _screen = screen;
- _type = type;
- _menu = menu;
- _scale = 0.9f;
- _alpha = 1.0f;
- }
+ #region Properties
///
@@ -70,124 +55,138 @@ namespace FarseerPhysics.SamplesFramework
///
public string Text
{
- get { return _text; }
- set { _text = value; }
+ get { return text; }
+ set { text = value; }
}
+
///
/// Gets or sets the position at which to draw this menu entry.
///
public Vector2 Position
{
- get { return _position; }
- set { _position = value; }
+ get { return position; }
+ set { position = value; }
}
- public float Alpha
+
+ #endregion
+
+ #region Events
+
+
+ ///
+ /// Event raised when the menu entry is selected.
+ ///
+ public event EventHandler Selected;
+
+
+ ///
+ /// Method for raising the Selected event.
+ ///
+ protected internal virtual void OnSelectEntry(PlayerIndex playerIndex)
{
- get { return _alpha; }
- set { _alpha = value; }
+ if (Selected != null)
+ Selected(this, new PlayerIndexEventArgs(playerIndex));
}
- public GameScreen Screen
+
+ #endregion
+
+ #region Initialization
+
+
+ ///
+ /// Constructs a new menu entry with the specified text.
+ ///
+ public MenuEntry(string text)
{
- get { return _screen; }
+ this.text = text;
}
- public void Initialize()
- {
- SpriteFont font = _menu.ScreenManager.Fonts.MenuSpriteFont;
- _baseOrigin = new Vector2(font.MeasureString(Text).X, font.MeasureString("M").Y) * 0.5f;
+ #endregion
- _width = font.MeasureString(Text).X * 0.8f;
- _height = font.MeasureString("M").Y * 0.8f;
- }
+ #region Update and Draw
- public bool IsExitItem()
- {
- return _type == EntryType.ExitItem;
- }
-
- public bool IsSelectable()
- {
- return _type != EntryType.Separator;
- }
-
- public bool IsBackItem()
- {
- return _type == EntryType.BackItem;
- }
///
/// Updates the menu entry.
///
- public void Update(bool isSelected, GameTime gameTime)
+ 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.
- if (_type != EntryType.Separator)
- {
- float fadeSpeed = (float)gameTime.ElapsedGameTime.TotalSeconds * 4;
- if (isSelected)
- {
- _selectionFade = Math.Min(_selectionFade + fadeSpeed, 1f);
- }
- else
- {
- _selectionFade = Math.Max(_selectionFade - fadeSpeed, 0f);
- }
- _scale = 0.7f + 0.1f * _selectionFade;
- }
+ float fadeSpeed = (float)gameTime.ElapsedGameTime.TotalSeconds * 4;
+
+ if (isSelected)
+ selectionFade = Math.Min(selectionFade + fadeSpeed, 1);
+ else
+ selectionFade = Math.Max(selectionFade - fadeSpeed, 0);
}
+
///
/// Draws the menu entry. This can be overridden to customize the appearance.
///
- public void Draw()
+ public virtual void Draw(MenuScreen screen, bool isSelected, GameTime gameTime)
{
- SpriteFont font = _menu.ScreenManager.Fonts.MenuSpriteFont;
- SpriteBatch batch = _menu.ScreenManager.SpriteBatch;
+ // 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
- Color color;
- if (_type == EntryType.Separator)
- {
- color = Color.DarkOrange;
- }
- else
- {
- // Draw the selected entry in yellow, otherwise white
- color = Color.Lerp(Color.White, new Color(255, 210, 0), _selectionFade);
- }
- color *= _alpha;
+ // 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.
- batch.DrawString(font, _text, _position - _baseOrigin * _scale + Vector2.One,
- Color.DarkSlateGray * _alpha * _alpha, 0, Vector2.Zero, _scale, SpriteEffects.None, 0);
- batch.DrawString(font, _text, _position - _baseOrigin * _scale, color, 0, Vector2.Zero, _scale,
- SpriteEffects.None, 0);
+ 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, scale, SpriteEffects.None, 0);
}
+
///
/// Queries how much space this menu entry requires.
///
- public int GetHeight()
+ public virtual int GetHeight(MenuScreen screen)
{
- return (int)_height;
+ return screen.ScreenManager.Font.LineSpacing;
}
+
///
/// Queries how wide the entry is, used for centering on the screen.
///
- public int GetWidth()
+ public virtual int GetWidth(MenuScreen screen)
{
- return (int)_width;
+ return (int)screen.ScreenManager.Font.MeasureString(Text).X;
}
+
+
+ #endregion
}
-}
\ No newline at end of file
+}
diff --git a/axios/ScreenSystem/MenuScreen.cs b/axios/ScreenSystem/MenuScreen.cs
index 2b649d6..b7fe332 100644
--- a/axios/ScreenSystem/MenuScreen.cs
+++ b/axios/ScreenSystem/MenuScreen.cs
@@ -1,235 +1,169 @@
+#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;
+using FarseerPhysics.SamplesFramework;
+#endregion
-namespace FarseerPhysics.SamplesFramework
+namespace GameStateManagement
{
///
/// 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.
///
- public class MenuScreen : GameScreen
+ abstract class MenuScreen : GameScreen
{
-#if WINDOWS || XBOX
- protected const float NumEntries = 15;
-#elif WINDOWS_PHONE
- protected const float NumEntries = 9;
-#endif
- protected List _menuEntries = new List();
- protected string _menuTitle;
- protected Vector2 _titlePosition;
- protected Vector2 _titleOrigin;
- protected int _selectedEntry;
- protected float _menuBorderTop;
- protected float _menuBorderBottom;
- protected float _menuBorderMargin;
- protected float _menuOffset;
- protected float _maxOffset;
+ #region Fields
- protected Texture2D _texScrollButton;
- protected Texture2D _texSlider;
+ List menuEntries = new List();
+ int selectedEntry = 0;
+ string menuTitle;
+
+ InputAction menuUp;
+ InputAction menuDown;
+ InputAction menuSelect;
+ InputAction menuCancel;
+
+ #endregion
+
+ #region Properties
+
+
+ ///
+ /// Gets the list of menu entries, so derived classes can add
+ /// or change the menu contents.
+ ///
+ protected IList MenuEntries
+ {
+ get { return menuEntries; }
+ }
+
+
+ #endregion
+
+ #region Initialization
- protected MenuButton _scrollUp;
- protected MenuButton _scrollDown;
- protected MenuButton _scrollSlider;
- protected bool _scrollLock;
///
/// Constructor.
///
public MenuScreen(string menuTitle)
{
- _menuTitle = menuTitle;
+ this.menuTitle = menuTitle;
- TransitionOnTime = TimeSpan.FromSeconds(0.7);
- TransitionOffTime = TimeSpan.FromSeconds(0.7);
- HasCursor = true;
+ TransitionOnTime = TimeSpan.FromSeconds(0.5);
+ TransitionOffTime = TimeSpan.FromSeconds(0.5);
+
+ menuUp = new InputAction(
+ new Buttons[] { Buttons.DPadUp, Buttons.LeftThumbstickUp },
+ new Keys[] { Keys.Up },
+ true);
+ menuDown = new InputAction(
+ new Buttons[] { Buttons.DPadDown, Buttons.LeftThumbstickDown },
+ new Keys[] { Keys.Down },
+ true);
+ menuSelect = new InputAction(
+ new Buttons[] { Buttons.A, Buttons.Start },
+ new Keys[] { Keys.Enter, Keys.Space },
+ true);
+ menuCancel = new InputAction(
+ new Buttons[] { Buttons.B, Buttons.Back },
+ new Keys[] { Keys.Escape },
+ true);
}
- public void AddMenuItem(string name, EntryType type, GameScreen screen)
- {
- MenuEntry entry = new MenuEntry(this, name, type, screen);
- _menuEntries.Add(entry);
- }
- public void AddMenuItem(MenuEntry me)
- {
- _menuEntries.Add(me);
- }
+ #endregion
- public override void LoadContent()
- {
- base.LoadContent();
-
- _texScrollButton = ScreenManager.Content.Load("Common/arrow");
- _texSlider = ScreenManager.Content.Load("Common/slider");
+ #region Handle Input
- //Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
- //float scrollBarPos = viewport.Width / 2f;
- //scrollBarPos -= _texScrollButton.Width + 2f;
-
-
-
- InitMenu();
-
-
-
- }
-
- public void InitMenu()
- {
- Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
- SpriteFont font = ScreenManager.Fonts.MenuSpriteFont;
- float scrollBarPos = viewport.Width / 2f;
-
- for (int i = 0; i < _menuEntries.Count; ++i)
- {
- _menuEntries[i].Initialize();
- scrollBarPos = Math.Min(scrollBarPos,
- (viewport.Width - _menuEntries[i].GetWidth()) / 2f);
- }
-
- _titleOrigin = font.MeasureString(_menuTitle) / 2f;
- _titlePosition = new Vector2(viewport.Width / 2f, font.MeasureString("M").Y / 2f + 10f);
-
- _menuBorderMargin = font.MeasureString("M").Y * 0.8f;
- _menuBorderTop = (viewport.Height - _menuBorderMargin * (NumEntries - 1)) / 2f;
- _menuBorderBottom = (viewport.Height + _menuBorderMargin * (NumEntries - 1)) / 2f;
-
- _menuOffset = 0f;
- _maxOffset = Math.Max(0f, (_menuEntries.Count - NumEntries) * _menuBorderMargin);
-
- _scrollUp = new MenuButton(_texScrollButton, false,
- new Vector2(scrollBarPos, _menuBorderTop - _texScrollButton.Height), this);
- _scrollDown = new MenuButton(_texScrollButton, true,
- new Vector2(scrollBarPos, _menuBorderBottom + _texScrollButton.Height), this);
- _scrollSlider = new MenuButton(_texSlider, false, new Vector2(scrollBarPos, _menuBorderTop), this);
-
- _scrollLock = false;
- }
-
- ///
- /// Returns the index of the menu entry at the position of the given mouse state.
- ///
- /// Index of menu entry if valid, -1 otherwise
- private int GetMenuEntryAt(Vector2 position)
- {
- if (this.TransitionPosition == 0f && this.ScreenState == SamplesFramework.ScreenState.Active)
- {
- int index = 0;
- foreach (MenuEntry entry in _menuEntries)
- {
- float width = entry.GetWidth();
- float height = entry.GetHeight();
- Rectangle rect = new Rectangle((int)(entry.Position.X - width / 2f),
- (int)(entry.Position.Y - height / 2f),
- (int)width, (int)height);
- if (rect.Contains((int)position.X, (int)position.Y) && entry.Alpha > 0.1f)
- {
- return index;
- }
- ++index;
- }
- }
- return -1;
- }
///
/// Responds to user input, changing the selected entry and accepting
/// or cancelling the menu.
///
- public override void HandleInput(InputHelper input, GameTime gameTime)
+ public override void HandleInput(GameTime gameTime, InputState input)
{
- // Mouse or touch on a menu item
- int hoverIndex = GetMenuEntryAt(input.Cursor);
- if (hoverIndex > -1 && _menuEntries[hoverIndex].IsSelectable() && !_scrollLock)
+ // For input tests 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;
+
+ // Move to the previous menu entry?
+ if (menuUp.Evaluate(input, ControllingPlayer, out playerIndex))
{
- _selectedEntry = hoverIndex;
- }
- else
- {
- _selectedEntry = -1;
+ selectedEntry--;
+
+ if (selectedEntry < 0)
+ selectedEntry = menuEntries.Count - 1;
}
- _scrollSlider.Hover = false;
- if (input.IsCursorValid)
+ // Move to the next menu entry?
+ if (menuDown.Evaluate(input, ControllingPlayer, out playerIndex))
{
- _scrollUp.Collide(input.Cursor);
- _scrollDown.Collide(input.Cursor);
- _scrollSlider.Collide(input.Cursor);
- }
- else
- {
- _scrollUp.Hover = false;
- _scrollDown.Hover = false;
- _scrollLock = false;
+ selectedEntry++;
+
+ if (selectedEntry >= menuEntries.Count)
+ selectedEntry = 0;
}
- // Accept or cancel the menu?
- if (input.IsMenuSelect() && _selectedEntry != -1)
+ if (menuSelect.Evaluate(input, ControllingPlayer, out playerIndex))
{
- if (_menuEntries[_selectedEntry].IsExitItem())
- {
- ScreenManager.Game.Exit();
- }
- else if (_menuEntries[_selectedEntry].IsBackItem())
- {
- this.ExitScreen();
- }
- else if (_menuEntries[_selectedEntry].Screen != null)
- {
- ScreenManager.AddScreen(_menuEntries[_selectedEntry].Screen);
- if (_menuEntries[_selectedEntry].Screen is IDemoScreen)
- {
- ScreenManager.AddScreen(
- new MessageBoxScreen((_menuEntries[_selectedEntry].Screen as IDemoScreen).GetDetails()));
- }
- }
+ OnSelectEntry(selectedEntry, playerIndex);
}
- else if (input.IsMenuCancel())
+ else if (menuCancel.Evaluate(input, ControllingPlayer, out playerIndex))
{
- if (this.ScreenState == SamplesFramework.ScreenState.Active && this.TransitionPosition == 0 && this.TransitionAlpha == 1)
- {
- //GameScreen[] screens = ScreenManager.GetScreens();
- //if (screens[screens.Length - 1] is BackgroundScreen ||| screens.Length )
- // ScreenManager.Game.Exit();
- //if (ScreenManager.GetScreens().Length == 2)
- // ScreenManager.Game.Exit();
- //else
- this.ExitScreen();
- }
- //ScreenManager.Game.Exit();
- }
-
- if (input.IsMenuPressed())
- {
- if (_scrollUp.Hover)
- {
- _menuOffset = Math.Max(_menuOffset - 200f * (float)gameTime.ElapsedGameTime.TotalSeconds, 0f);
- _scrollLock = false;
- }
- if (_scrollDown.Hover)
- {
- _menuOffset = Math.Min(_menuOffset + 200f * (float)gameTime.ElapsedGameTime.TotalSeconds, _maxOffset);
- _scrollLock = false;
- }
- if (_scrollSlider.Hover)
- {
- _scrollLock = true;
- }
- }
- if (input.IsMenuReleased())
- {
- _scrollLock = false;
- }
- if (_scrollLock)
- {
- _scrollSlider.Hover = true;
- _menuOffset = Math.Max(Math.Min(((input.Cursor.Y - _menuBorderTop) / (_menuBorderBottom - _menuBorderTop)) * _maxOffset, _maxOffset), 0f);
+ OnCancel(playerIndex);
}
}
+
+ ///
+ /// Handler for when the user has chosen a menu entry.
+ ///
+ protected virtual void OnSelectEntry(int entryIndex, PlayerIndex playerIndex)
+ {
+ menuEntries[entryIndex].OnSelectEntry(playerIndex);
+ }
+
+
+ ///
+ /// Handler for when the user has cancelled the menu.
+ ///
+ protected virtual void OnCancel(PlayerIndex playerIndex)
+ {
+ ExitScreen();
+ }
+
+
+ ///
+ /// Helper overload makes it easy to use OnCancel as a MenuEntry event handler.
+ ///
+ protected void OnCancel(object sender, PlayerIndexEventArgs e)
+ {
+ OnCancel(e.PlayerIndex);
+ }
+
+
+ #endregion
+
+ #region Update and Draw
+
+
///
/// 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.
@@ -241,69 +175,49 @@ namespace FarseerPhysics.SamplesFramework
// the movement slow down as it nears the end).
float transitionOffset = (float)Math.Pow(TransitionPosition, 2);
- Vector2 position = Vector2.Zero;
- position.Y = _menuBorderTop - _menuOffset;
+ // start at Y = 175; each X value is generated per entry
+ Vector2 position = new Vector2(0f, 175f);
// update each menu entry's location in turn
- for (int i = 0; i < _menuEntries.Count; ++i)
+ for (int i = 0; i < menuEntries.Count; i++)
{
- position.X = ScreenManager.GraphicsDevice.Viewport.Width / 2f;
+ 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 * 256;
- }
+ position.X += transitionOffset * 512;
// set the entry's position
- _menuEntries[i].Position = position;
-
- if (position.Y < _menuBorderTop)
- {
- _menuEntries[i].Alpha = 1f -
- Math.Min(_menuBorderTop - position.Y, _menuBorderMargin) / _menuBorderMargin;
- }
- else if (position.Y > _menuBorderBottom)
- {
- _menuEntries[i].Alpha = 1f -
- Math.Min(position.Y - _menuBorderBottom, _menuBorderMargin) /
- _menuBorderMargin;
- }
- else
- {
- _menuEntries[i].Alpha = 1f;
- }
+ menuEntry.Position = position;
// move down for the next entry the size of this entry
- position.Y += _menuEntries[i].GetHeight();
+ position.Y += menuEntry.GetHeight(this);
}
- Vector2 scrollPos = _scrollSlider.Position;
- scrollPos.Y = MathHelper.Lerp(_menuBorderTop, _menuBorderBottom, _menuOffset / _maxOffset);
- _scrollSlider.Position = scrollPos;
}
+
///
/// Updates the menu.
///
public override void Update(GameTime gameTime, bool otherScreenHasFocus,
- bool coveredByOtherScreen)
+ bool coveredByOtherScreen)
{
base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
// Update each nested MenuEntry object.
- for (int i = 0; i < _menuEntries.Count; ++i)
+ for (int i = 0; i < menuEntries.Count; i++)
{
- bool isSelected = IsActive && (i == _selectedEntry);
- _menuEntries[i].Update(isSelected, gameTime);
- }
+ bool isSelected = IsActive && (i == selectedEntry);
- _scrollUp.Update(gameTime);
- _scrollDown.Update(gameTime);
- _scrollSlider.Update(gameTime);
+ menuEntries[i].Update(this, isSelected, gameTime);
+ }
}
+
///
/// Draws the menu.
///
@@ -312,30 +226,42 @@ namespace FarseerPhysics.SamplesFramework
// make sure our entries are in the right place before we draw them
UpdateMenuEntryLocations();
+ GraphicsDevice graphics = ScreenManager.GraphicsDevice;
SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
- SpriteFont font = ScreenManager.Fonts.MenuSpriteFont;
+ SpriteFont font = ScreenManager.Font;
spriteBatch.Begin();
+
// Draw each menu entry in turn.
- for (int i = 0; i < _menuEntries.Count; ++i)
+ for (int i = 0; i < menuEntries.Count; i++)
{
- bool isSelected = IsActive && (i == _selectedEntry);
- _menuEntries[i].Draw();
+ 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).
- Vector2 transitionOffset = new Vector2(0f, (float)Math.Pow(TransitionPosition, 2) * 100f);
+ float transitionOffset = (float)Math.Pow(TransitionPosition, 2);
+
+ // Draw the menu title centered on the screen
+ Vector2 titlePosition = new Vector2(graphics.Viewport.Width / 2, 80);
+ Vector2 titleOrigin = font.MeasureString(menuTitle) / 2;
+ Color titleColor = new Color(192, 192, 192) * TransitionAlpha;
+ float titleScale = 1.25f;
+
+ titlePosition.Y -= transitionOffset * 100;
+
+ spriteBatch.DrawString(font, menuTitle, titlePosition, titleColor, 0,
+ titleOrigin, titleScale, SpriteEffects.None, 0);
- spriteBatch.DrawString(font, _menuTitle, _titlePosition - transitionOffset + Vector2.One * 2f, Color.Black, 0,
- _titleOrigin, 1f, SpriteEffects.None, 0);
- spriteBatch.DrawString(font, _menuTitle, _titlePosition - transitionOffset, new Color(255, 210, 0), 0,
- _titleOrigin, 1f, SpriteEffects.None, 0);
- _scrollUp.Draw();
- _scrollSlider.Draw();
- _scrollDown.Draw();
spriteBatch.End();
}
+
+
+ #endregion
}
-}
\ No newline at end of file
+}
diff --git a/axios/ScreenSystem/MessageBoxScreen.cs b/axios/ScreenSystem/MessageBoxScreen.cs
index d3c9826..55b7a93 100644
--- a/axios/ScreenSystem/MessageBoxScreen.cs
+++ b/axios/ScreenSystem/MessageBoxScreen.cs
@@ -1,36 +1,87 @@
-using System;
+#region File Description
+//-----------------------------------------------------------------------------
+// MessageBoxScreen.cs
+//
+// Microsoft 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;
+using Microsoft.Xna.Framework.Input;
+using GameStateManagement;
+#endregion
-namespace FarseerPhysics.SamplesFramework
+namespace GameStateManagement
{
///
/// A popup message box screen, used to display "are you sure?"
/// confirmation messages.
///
- public class MessageBoxScreen : GameScreen
+ class MessageBoxScreen : GameScreen
{
- protected Rectangle _backgroundRectangle;
- protected Texture2D _gradientTexture;
- protected string _message;
- protected Vector2 _textPosition;
+ #region Fields
+ string message;
+ Texture2D gradientTexture;
+
+ InputAction menuSelect;
+ InputAction menuCancel;
+
+ #endregion
+
+ #region Events
+
+ public event EventHandler Accepted;
+ public event EventHandler Cancelled;
+
+ #endregion
+
+ #region Initialization
+
+
+ ///
+ /// Constructor automatically includes the standard "A=ok, B=cancel"
+ /// usage text prompt.
+ ///
public MessageBoxScreen(string message)
+ : this(message, true)
+ { }
+
+
+ ///
+ /// Constructor lets the caller specify whether to include the standard
+ /// "A=ok, B=cancel" usage text prompt.
+ ///
+ public MessageBoxScreen(string message, bool includeUsageText)
{
- _message = message;
+ const string usageText = "\nA button, Space, Enter = ok" +
+ "\nB button, Esc = cancel";
+
+ if (includeUsageText)
+ this.message = message + usageText;
+ else
+ this.message = message;
IsPopup = true;
- HasCursor = true;
- TransitionOnTime = TimeSpan.FromSeconds(0.4);
- TransitionOffTime = TimeSpan.FromSeconds(0.4);
+ TransitionOnTime = TimeSpan.FromSeconds(0.2);
+ TransitionOffTime = TimeSpan.FromSeconds(0.2);
+
+ menuSelect = new InputAction(
+ new Buttons[] { Buttons.A, Buttons.Start },
+ new Keys[] { Keys.Space, Keys.Enter },
+ true);
+ menuCancel = new InputAction(
+ new Buttons[] { Buttons.B, Buttons.Back },
+ new Keys[] { Keys.Escape, Keys.Back },
+ true);
}
- public MessageBoxScreen()
- {
- IsPopup = true;
- }
///
/// Loads graphics content for this screen. This uses the shared ContentManager
@@ -38,62 +89,98 @@ namespace FarseerPhysics.SamplesFramework
/// Whenever a subsequent MessageBoxScreen tries to load this same content,
/// it will just get back another reference to the already loaded data.
///
- public override void LoadContent()
+ public override void Activate(bool instancePreserved)
{
- SpriteFont font = ScreenManager.Fonts.DetailsFont;
- ContentManager content = ScreenManager.Game.Content;
- _gradientTexture = content.Load("Common/popup");
-
- // Center the message text in the viewport.
- Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
- Vector2 viewportSize = new Vector2(viewport.Width, viewport.Height);
- Vector2 textSize = font.MeasureString(_message);
- _textPosition = (viewportSize - textSize) / 2;
-
- // The background includes a border somewhat larger than the text itself.
- const int hPad = 32;
- const int vPad = 16;
-
- _backgroundRectangle = new Rectangle((int)_textPosition.X - hPad,
- (int)_textPosition.Y - vPad,
- (int)textSize.X + hPad * 2,
- (int)textSize.Y + vPad * 2);
+ if (!instancePreserved)
+ {
+ ContentManager content = ScreenManager.Game.Content;
+ gradientTexture = content.Load("gradient");
+ }
}
+
+ #endregion
+
+ #region Handle Input
+
+
///
/// Responds to user input, accepting or cancelling the message box.
///
- public override void HandleInput(InputHelper input, GameTime gameTime)
+ public override void HandleInput(GameTime gameTime, InputState input)
{
+ PlayerIndex playerIndex;
- if (input.IsMenuSelect() || input.IsMenuCancel() ||
- input.IsNewMouseButtonPress(MouseButtons.LeftButton))
+ // 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 our Accepted and
+ // Cancelled events, so they can tell which player triggered them.
+ if (menuSelect.Evaluate(input, ControllingPlayer, out playerIndex))
{
+ // Raise the accepted event, then exit the message box.
+ if (Accepted != null)
+ Accepted(this, new PlayerIndexEventArgs(playerIndex));
+
+ ExitScreen();
+ }
+ else if (menuCancel.Evaluate(input, ControllingPlayer, out playerIndex))
+ {
+ // Raise the cancelled event, then exit the message box.
+ if (Cancelled != null)
+ Cancelled(this, new PlayerIndexEventArgs(playerIndex));
+
ExitScreen();
}
}
+
+ #endregion
+
+ #region Draw
+
+
///
/// Draws the message box.
///
public override void Draw(GameTime gameTime)
{
SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
- SpriteFont font = ScreenManager.Fonts.DetailsFont;
+ SpriteFont font = ScreenManager.Font;
+
+ // Darken down any other screens that were drawn beneath the popup.
+ ScreenManager.FadeBackBufferToBlack(TransitionAlpha * 2 / 3);
+
+ // Center the message text in the viewport.
+ Viewport viewport = ScreenManager.GraphicsDevice.Viewport;
+ Vector2 viewportSize = new Vector2(viewport.Width, viewport.Height);
+ Vector2 textSize = font.MeasureString(message);
+ Vector2 textPosition = (viewportSize - textSize) / 2;
+
+ // The background includes a border somewhat larger than the text itself.
+ const int hPad = 32;
+ const int vPad = 16;
+
+ Rectangle backgroundRectangle = new Rectangle((int)textPosition.X - hPad,
+ (int)textPosition.Y - vPad,
+ (int)textSize.X + hPad * 2,
+ (int)textSize.Y + vPad * 2);
// Fade the popup alpha during transitions.
- Color color = Color.White * TransitionAlpha * (2f / 3f);
+ Color color = Color.White * TransitionAlpha;
spriteBatch.Begin();
// Draw the background rectangle.
- spriteBatch.Draw(_gradientTexture, _backgroundRectangle, color);
+ spriteBatch.Draw(gradientTexture, backgroundRectangle, color);
// Draw the message box text.
- spriteBatch.DrawString(font, _message, _textPosition + Vector2.One, Color.Black);
- spriteBatch.DrawString(font, _message, _textPosition, Color.White);
+ spriteBatch.DrawString(font, message, textPosition, color);
spriteBatch.End();
}
+
+
+ #endregion
}
-}
\ No newline at end of file
+}
diff --git a/axios/ScreenSystem/PhysicsGameScreen.cs b/axios/ScreenSystem/PhysicsGameScreen.cs
index 30fc9f0..fafc036 100644
--- a/axios/ScreenSystem/PhysicsGameScreen.cs
+++ b/axios/ScreenSystem/PhysicsGameScreen.cs
@@ -6,9 +6,10 @@ using FarseerPhysics.Dynamics.Joints;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Input;
+using FarseerPhysics.SamplesFramework;
using Axios.Engine;
-namespace FarseerPhysics.SamplesFramework
+namespace GameStateManagement
{
public class PhysicsGameScreen : GameScreen
{
@@ -47,48 +48,51 @@ namespace FarseerPhysics.SamplesFramework
_agentTorque = torque;
}
-
- public override void LoadContent()
+
+ public override void Activate(bool instancePreserved)
{
- base.LoadContent();
-
- //We enable diagnostics to show get values for our performance counters.
- Settings.EnableDiagnostics = true;
-
- if (World == null)
+ if (!instancePreserved)
{
- World = new World(Vector2.Zero);
- }
- else
- {
- World.Clear();
- }
+ base.Activate(instancePreserved);
- if (DebugView == null)
- {
- if (!Axios.Settings.ScreenSaver)
+ //We enable diagnostics to show get values for our performance counters.
+ Settings.EnableDiagnostics = true;
+
+ if (World == null)
{
- DebugView = new DebugViewXNA(World);
- DebugView.RemoveFlags(DebugViewFlags.Shape);
- DebugView.RemoveFlags(DebugViewFlags.Joint);
- DebugView.DefaultShapeColor = Color.White;
- DebugView.SleepingShapeColor = Color.LightGray;
- DebugView.LoadContent(ScreenManager.GraphicsDevice, ScreenManager.Content);
+ World = new World(Vector2.Zero);
+ }
+ else
+ {
+ World.Clear();
}
- }
- if (Camera == null)
- {
- Camera = new Camera2D(ScreenManager.GraphicsDevice);
- }
- else
- {
- Camera.ResetCamera();
- }
+ if (DebugView == null)
+ {
+ if (!Axios.Settings.ScreenSaver)
+ {
+ DebugView = new DebugViewXNA(World);
+ DebugView.RemoveFlags(DebugViewFlags.Shape);
+ DebugView.RemoveFlags(DebugViewFlags.Joint);
+ DebugView.DefaultShapeColor = Color.White;
+ DebugView.SleepingShapeColor = Color.LightGray;
+ DebugView.LoadContent(ScreenManager.GraphicsDevice, ScreenManager.Content);
+ }
+ }
- // Loading may take a while... so prevent the game from "catching up" once we finished loading
- ScreenManager.Game.ResetElapsedTime();
+ if (Camera == null)
+ {
+ Camera = new Camera2D(ScreenManager.GraphicsDevice);
+ }
+ else
+ {
+ Camera.ResetCamera();
+ }
+
+ // Loading may take a while... so prevent the game from "catching up" once we finished loading
+ ScreenManager.Game.ResetElapsedTime();
+ }
}
public override void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen)
@@ -110,12 +114,13 @@ namespace FarseerPhysics.SamplesFramework
{
}
- public override void HandleInput(InputHelper input, GameTime gameTime)
+ public override void HandleInput(GameTime gameTime, InputState input)
{
#if DEBUG
// Control debug view
- if (input.IsNewButtonPress(Buttons.Start))
+ PlayerIndex player;
+ if (input.IsNewButtonPress(Buttons.Start, ControllingPlayer.Value, out player))
{
EnableOrDisableFlag(DebugViewFlags.Shape);
EnableOrDisableFlag(DebugViewFlags.DebugPanel);
@@ -126,37 +131,37 @@ namespace FarseerPhysics.SamplesFramework
EnableOrDisableFlag(DebugViewFlags.Controllers);
}
- if (input.IsNewKeyPress(Keys.F1))
+ if (input.IsNewKeyPress(Keys.F1, ControllingPlayer.Value, out player))
{
EnableOrDisableFlag(DebugViewFlags.Shape);
}
- if (input.IsNewKeyPress(Keys.F2))
+ if (input.IsNewKeyPress(Keys.F2, ControllingPlayer.Value, out player))
{
EnableOrDisableFlag(DebugViewFlags.DebugPanel);
EnableOrDisableFlag(DebugViewFlags.PerformanceGraph);
}
- if (input.IsNewKeyPress(Keys.F3))
+ if (input.IsNewKeyPress(Keys.F3, ControllingPlayer.Value, out player))
{
EnableOrDisableFlag(DebugViewFlags.Joint);
}
- if (input.IsNewKeyPress(Keys.F4))
+ if (input.IsNewKeyPress(Keys.F4, ControllingPlayer.Value, out player))
{
EnableOrDisableFlag(DebugViewFlags.ContactPoints);
EnableOrDisableFlag(DebugViewFlags.ContactNormals);
}
- if (input.IsNewKeyPress(Keys.F5))
+ if (input.IsNewKeyPress(Keys.F5, ControllingPlayer.Value, out player))
{
EnableOrDisableFlag(DebugViewFlags.PolygonPoints);
}
- if (input.IsNewKeyPress(Keys.F6))
+ if (input.IsNewKeyPress(Keys.F6, ControllingPlayer.Value, out player))
{
EnableOrDisableFlag(DebugViewFlags.Controllers);
}
- if (input.IsNewKeyPress(Keys.F7))
+ if (input.IsNewKeyPress(Keys.F7, ControllingPlayer.Value, out player))
{
EnableOrDisableFlag(DebugViewFlags.CenterOfMass);
}
- if (input.IsNewKeyPress(Keys.F8))
+ if (input.IsNewKeyPress(Keys.F8, ControllingPlayer.Value, out player))
{
EnableOrDisableFlag(DebugViewFlags.AABB);
}
@@ -181,7 +186,7 @@ namespace FarseerPhysics.SamplesFramework
if (input.IsNewButtonPress(Buttons.Back) || input.IsNewKeyPress(Keys.Escape))
{
- if (this.ScreenState == SamplesFramework.ScreenState.Active && this.TransitionPosition == 0 && this.TransitionAlpha == 1)
+ if (this.ScreenState == GameStateManagement.ScreenState.Active && this.TransitionPosition == 0 && this.TransitionAlpha == 1)
{ //Give the screens a chance to transition
CleanUp();
@@ -191,9 +196,10 @@ namespace FarseerPhysics.SamplesFramework
}
base.HandleInput(input, gameTime);
}
-
- public virtual void HandleCursor(InputHelper input)
+
+ public virtual void HandleCursor(InputState input)
{
+ PlayerIndex player;
Vector2 position = Camera.ConvertScreenToWorld(input.Cursor);
if ((input.IsNewButtonPress(Buttons.A) ||
@@ -211,8 +217,9 @@ namespace FarseerPhysics.SamplesFramework
}
}
- if ((input.IsNewButtonRelease(Buttons.A) ||
- input.IsNewMouseButtonRelease(MouseButtons.LeftButton)) &&
+
+ if ((input.IsNewButtonRelease(Buttons.A, ControllingPlayer.Value, out player) ||
+ input.IsNewMouseButtonRelease(MouseButtons.LeftButton, ControllingPlayer.Value, out player)) &&
_fixedMouseJoint != null)
{
World.RemoveJoint(_fixedMouseJoint);
diff --git a/axios/ScreenSystem/ScreenManagerComponent.cs b/axios/ScreenSystem/ScreenManagerComponent.cs
index 2705ce0..7303f72 100644
--- a/axios/ScreenSystem/ScreenManagerComponent.cs
+++ b/axios/ScreenSystem/ScreenManagerComponent.cs
@@ -3,9 +3,11 @@ using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input.Touch;
+using FarseerPhysics.SamplesFramework;
-namespace FarseerPhysics.SamplesFramework
+namespace GameStateManagement
{
+ /*
///
/// The screen manager is a component which manages one or more GameScreen
/// instances. It maintains a stack of screens, calls their Update and Draw
@@ -299,5 +301,5 @@ namespace FarseerPhysics.SamplesFramework
{
return _screens.ToArray();
}
- }
+ }*/
}
\ No newline at end of file