diff --git a/axios/ScreenSystem/Button.cs b/axios/ScreenSystem/Button.cs
new file mode 100644
index 0000000..1cd60d7
--- /dev/null
+++ b/axios/ScreenSystem/Button.cs
@@ -0,0 +1,191 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// Button.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+using System;
+using GameStateManagement;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+
+namespace GameStateManagement
+{
+ ///
+ /// A special button that handles toggling between "On" and "Off"
+ ///
+ class BooleanButton : Button
+ {
+ private string option;
+ private bool value;
+
+ ///
+ /// Creates a new BooleanButton.
+ ///
+ /// The string text to display for the option.
+ /// The initial value of the button.
+ public BooleanButton(string option, bool value)
+ : base(option)
+ {
+ this.option = option;
+ this.value = value;
+
+ GenerateText();
+ }
+
+ protected override void OnTapped()
+ {
+ // When tapped we need to toggle the value and regenerate the text
+ value = !value;
+ GenerateText();
+
+ base.OnTapped();
+ }
+
+ ///
+ /// Helper that generates the actual Text value the base class uses for drawing.
+ ///
+ private void GenerateText()
+ {
+ Text = string.Format("{0}: {1}", option, value ? "On" : "Off");
+ }
+ }
+
+ ///
+ /// Represents a touchable button.
+ ///
+ class Button
+ {
+ ///
+ /// The text displayed in the button.
+ ///
+ public string Text = "Button";
+
+ ///
+ /// The position of the top-left corner of the button.
+ ///
+ public Vector2 Position = Vector2.Zero;
+
+ ///
+ /// The size of the button.
+ ///
+ public Vector2 Size = new Vector2(250, 75);
+
+ ///
+ /// The thickness of the border drawn for the button.
+ ///
+ public int BorderThickness = 4;
+
+ ///
+ /// The color of the button border.
+ ///
+ public Color BorderColor = new Color(200, 200, 200);
+
+ ///
+ /// The color of the button background.
+ ///
+ public Color FillColor = new Color(100, 100, 100) * .75f;
+
+ ///
+ /// The color of the text.
+ ///
+ public Color TextColor = Color.White;
+
+ ///
+ /// The opacity of the button.
+ ///
+ public float Alpha = 0f;
+
+ ///
+ /// Invoked when the button is tapped.
+ ///
+ public event EventHandler Tapped;
+
+ ///
+ /// Creates a new Button.
+ ///
+ /// The text to display in the button.
+ public Button(string text)
+ {
+ Text = text;
+ }
+
+ ///
+ /// Invokes the Tapped event and allows subclasses to perform actions when tapped.
+ ///
+ protected virtual void OnTapped()
+ {
+ if (Tapped != null)
+ Tapped(this, EventArgs.Empty);
+ }
+
+ ///
+ /// Passes a tap location to the button for handling.
+ ///
+ /// The location of the tap.
+ /// True if the button was tapped, false otherwise.
+ public bool HandleTap(Vector2 tap)
+ {
+ if (tap.X >= Position.X &&
+ tap.Y >= Position.Y &&
+ tap.X <= Position.X + Size.X &&
+ tap.Y <= Position.Y + Size.Y)
+ {
+ OnTapped();
+ return true;
+ }
+
+ return false;
+ }
+
+ ///
+ /// Draws the button
+ ///
+ /// The screen drawing the button
+ public void Draw(GameScreen screen)
+ {
+ // Grab some common items from the ScreenManager
+ SpriteBatch spriteBatch = screen.ScreenManager.SpriteBatch;
+ SpriteFont font = screen.ScreenManager.Font;
+ Texture2D blank = screen.ScreenManager.BlankTexture;
+
+ // Compute the button's rectangle
+ Rectangle r = new Rectangle(
+ (int)Position.X,
+ (int)Position.Y,
+ (int)Size.X,
+ (int)Size.Y);
+
+ // Fill the button
+ spriteBatch.Draw(blank, r, FillColor * Alpha);
+
+ // Draw the border
+ spriteBatch.Draw(
+ blank,
+ new Rectangle(r.Left, r.Top, r.Width, BorderThickness),
+ BorderColor * Alpha);
+ spriteBatch.Draw(
+ blank,
+ new Rectangle(r.Left, r.Top, BorderThickness, r.Height),
+ BorderColor * Alpha);
+ spriteBatch.Draw(
+ blank,
+ new Rectangle(r.Right - BorderThickness, r.Top, BorderThickness, r.Height),
+ BorderColor * Alpha);
+ spriteBatch.Draw(
+ blank,
+ new Rectangle(r.Left, r.Bottom - BorderThickness, r.Width, BorderThickness),
+ BorderColor * Alpha);
+
+ // Draw the text centered in the button
+ Vector2 textSize = font.MeasureString(Text);
+ Vector2 textPosition = new Vector2(r.Center.X, r.Center.Y) - textSize / 2f;
+ textPosition.X = (int)textPosition.X;
+ textPosition.Y = (int)textPosition.Y;
+ spriteBatch.DrawString(font, Text, textPosition, TextColor * Alpha);
+ }
+ }
+}
diff --git a/axios/ScreenSystem/GameplayScreen.cs b/axios/ScreenSystem/GameplayScreen.cs
new file mode 100644
index 0000000..a2be8be
--- /dev/null
+++ b/axios/ScreenSystem/GameplayScreen.cs
@@ -0,0 +1,265 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// GameplayScreen.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using System;
+using System.Threading;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Content;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Input;
+using GameStateManagement;
+#endregion
+
+namespace GameStateManagementSample
+{
+ ///
+ /// This screen implements the actual game logic. It is just a
+ /// placeholder to get the idea across: you'll probably want to
+ /// put some more interesting gameplay in here!
+ ///
+ class GameplayScreen : GameScreen
+ {
+ #region Fields
+
+ ContentManager content;
+ SpriteFont gameFont;
+
+ Vector2 playerPosition = new Vector2(100, 100);
+ Vector2 enemyPosition = new Vector2(100, 100);
+
+ Random random = new Random();
+
+ float pauseAlpha;
+
+ InputAction pauseAction;
+
+ #endregion
+
+ #region Initialization
+
+
+ ///
+ /// Constructor.
+ ///
+ public GameplayScreen()
+ {
+ TransitionOnTime = TimeSpan.FromSeconds(1.5);
+ TransitionOffTime = TimeSpan.FromSeconds(0.5);
+
+ pauseAction = new InputAction(
+ new Buttons[] { Buttons.Start, Buttons.Back },
+ new Keys[] { Keys.Escape },
+ true);
+ }
+
+
+ ///
+ /// Load graphics content for the game.
+ ///
+ public override void Activate(bool instancePreserved)
+ {
+ if (!instancePreserved)
+ {
+ if (content == null)
+ content = new ContentManager(ScreenManager.Game.Services, "Content");
+
+ gameFont = content.Load("gamefont");
+
+ // A real game would probably have more content than this sample, so
+ // it would take longer to load. We simulate that by delaying for a
+ // while, giving you a chance to admire the beautiful loading screen.
+ Thread.Sleep(1000);
+
+ // once the load has finished, we use ResetElapsedTime to tell the game's
+ // timing mechanism that we have just finished a very long frame, and that
+ // it should not try to catch up.
+ ScreenManager.Game.ResetElapsedTime();
+ }
+
+#if WINDOWS_PHONE
+ if (Microsoft.Phone.Shell.PhoneApplicationService.Current.State.ContainsKey("PlayerPosition"))
+ {
+ playerPosition = (Vector2)Microsoft.Phone.Shell.PhoneApplicationService.Current.State["PlayerPosition"];
+ enemyPosition = (Vector2)Microsoft.Phone.Shell.PhoneApplicationService.Current.State["EnemyPosition"];
+ }
+#endif
+ }
+
+
+ public override void Deactivate()
+ {
+#if WINDOWS_PHONE
+ Microsoft.Phone.Shell.PhoneApplicationService.Current.State["PlayerPosition"] = playerPosition;
+ Microsoft.Phone.Shell.PhoneApplicationService.Current.State["EnemyPosition"] = enemyPosition;
+#endif
+
+ base.Deactivate();
+ }
+
+
+ ///
+ /// Unload graphics content used by the game.
+ ///
+ public override void Unload()
+ {
+ content.Unload();
+
+#if WINDOWS_PHONE
+ Microsoft.Phone.Shell.PhoneApplicationService.Current.State.Remove("PlayerPosition");
+ Microsoft.Phone.Shell.PhoneApplicationService.Current.State.Remove("EnemyPosition");
+#endif
+ }
+
+
+ #endregion
+
+ #region Update and Draw
+
+
+ ///
+ /// Updates the state of the game. This method checks the GameScreen.IsActive
+ /// property, so the game will stop updating when the pause menu is active,
+ /// or if you tab away to a different application.
+ ///
+ public override void Update(GameTime gameTime, bool otherScreenHasFocus,
+ bool coveredByOtherScreen)
+ {
+ base.Update(gameTime, otherScreenHasFocus, false);
+
+ // Gradually fade in or out depending on whether we are covered by the pause screen.
+ if (coveredByOtherScreen)
+ pauseAlpha = Math.Min(pauseAlpha + 1f / 32, 1);
+ else
+ pauseAlpha = Math.Max(pauseAlpha - 1f / 32, 0);
+
+ if (IsActive)
+ {
+ // Apply some random jitter to make the enemy move around.
+ const float randomization = 10;
+
+ enemyPosition.X += (float)(random.NextDouble() - 0.5) * randomization;
+ enemyPosition.Y += (float)(random.NextDouble() - 0.5) * randomization;
+
+ // Apply a stabilizing force to stop the enemy moving off the screen.
+ Vector2 targetPosition = new Vector2(
+ ScreenManager.GraphicsDevice.Viewport.Width / 2 - gameFont.MeasureString("Insert Gameplay Here").X / 2,
+ 200);
+
+ enemyPosition = Vector2.Lerp(enemyPosition, targetPosition, 0.05f);
+
+ // TODO: this game isn't very fun! You could probably improve
+ // it by inserting something more interesting in this space :-)
+ }
+ }
+
+
+ ///
+ /// Lets the game respond to player input. Unlike the Update method,
+ /// this will only be called when the gameplay screen is active.
+ ///
+ public override void HandleInput(GameTime gameTime, InputState input)
+ {
+ if (input == null)
+ throw new ArgumentNullException("input");
+
+ // Look up inputs for the active player profile.
+ int playerIndex = (int)ControllingPlayer.Value;
+
+ KeyboardState keyboardState = input.CurrentKeyboardStates[playerIndex];
+ GamePadState gamePadState = input.CurrentGamePadStates[playerIndex];
+
+ // The game pauses either if the user presses the pause button, or if
+ // they unplug the active gamepad. This requires us to keep track of
+ // whether a gamepad was ever plugged in, because we don't want to pause
+ // on PC if they are playing with a keyboard and have no gamepad at all!
+ bool gamePadDisconnected = !gamePadState.IsConnected &&
+ input.GamePadWasConnected[playerIndex];
+
+ PlayerIndex player;
+ if (pauseAction.Evaluate(input, ControllingPlayer, out player) || gamePadDisconnected)
+ {
+#if WINDOWS_PHONE
+ ScreenManager.AddScreen(new PhonePauseScreen(), ControllingPlayer);
+#else
+ ScreenManager.AddScreen(new PauseMenuScreen(), ControllingPlayer);
+#endif
+ }
+ else
+ {
+ // Otherwise move the player position.
+ Vector2 movement = Vector2.Zero;
+
+ if (keyboardState.IsKeyDown(Keys.Left))
+ movement.X--;
+
+ if (keyboardState.IsKeyDown(Keys.Right))
+ movement.X++;
+
+ if (keyboardState.IsKeyDown(Keys.Up))
+ movement.Y--;
+
+ if (keyboardState.IsKeyDown(Keys.Down))
+ movement.Y++;
+
+ Vector2 thumbstick = gamePadState.ThumbSticks.Left;
+
+ movement.X += thumbstick.X;
+ movement.Y -= thumbstick.Y;
+
+ if (input.TouchState.Count > 0)
+ {
+ Vector2 touchPosition = input.TouchState[0].Position;
+ Vector2 direction = touchPosition - playerPosition;
+ direction.Normalize();
+ movement += direction;
+ }
+
+ if (movement.Length() > 1)
+ movement.Normalize();
+
+ playerPosition += movement * 8f;
+ }
+ }
+
+
+ ///
+ /// Draws the gameplay screen.
+ ///
+ public override void Draw(GameTime gameTime)
+ {
+ // This game has a blue background. Why? Because!
+ ScreenManager.GraphicsDevice.Clear(ClearOptions.Target,
+ Color.CornflowerBlue, 0, 0);
+
+ // Our player and enemy are both actually just text strings.
+ SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
+
+ spriteBatch.Begin();
+
+ spriteBatch.DrawString(gameFont, "// TODO", playerPosition, Color.Green);
+
+ spriteBatch.DrawString(gameFont, "Insert Gameplay Here",
+ enemyPosition, Color.DarkRed);
+
+ spriteBatch.End();
+
+ // If the game is transitioning on or off, fade it out to black.
+ if (TransitionPosition > 0 || pauseAlpha > 0)
+ {
+ float alpha = MathHelper.Lerp(1f - TransitionAlpha, 1f, pauseAlpha / 2);
+
+ ScreenManager.FadeBackBufferToBlack(alpha);
+ }
+ }
+
+
+ #endregion
+ }
+}
diff --git a/axios/ScreenSystem/IScreenFactory.cs b/axios/ScreenSystem/IScreenFactory.cs
new file mode 100644
index 0000000..10a81fb
--- /dev/null
+++ b/axios/ScreenSystem/IScreenFactory.cs
@@ -0,0 +1,49 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// IScreenFactory.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+using System;
+
+namespace GameStateManagement
+{
+ ///
+ /// Defines an object that can create a screen when given its type.
+ ///
+ /// The ScreenManager attempts to handle tombstoning on Windows Phone by creating an XML
+ /// document that has a list of the screens currently in the manager. When the game is
+ /// reactivated, the ScreenManager needs to create instances of those screens. However
+ /// since there is no restriction that a particular GameScreen subclass has a parameterless
+ /// constructor, there is no way the ScreenManager alone could create those instances.
+ ///
+ /// IScreenFactory fills this gap by providing an interface the game should implement to
+ /// act as a translation from type to instance. The ScreenManager locates the IScreenFactory
+ /// from the Game.Services collection and passes each screen type to the factory, expecting
+ /// to get the correct GameScreen out.
+ ///
+ /// If your game screens all have parameterless constructors, the minimal implementation of
+ /// this interface would look like this:
+ ///
+ /// return Activator.CreateInstance(screenType) as GameScreen;
+ ///
+ /// If you have screens with constructors that take arguments, you will need to ensure that
+ /// you can read these arguments from storage or generate new ones, then construct the screen
+ /// based on the type.
+ ///
+ /// The ScreenFactory type in the sample game has the minimal implementation along with some
+ /// extra comments showing a potentially more complex example of how to implement IScreenFactory.
+ ///
+ public interface IScreenFactory
+ {
+ ///
+ /// Creates a GameScreen from the given type.
+ ///
+ /// The type of screen to create.
+ /// The newly created screen.
+ GameScreen CreateScreen(Type screenType);
+ }
+}
diff --git a/axios/ScreenSystem/InputAction.cs b/axios/ScreenSystem/InputAction.cs
new file mode 100644
index 0000000..97e9b7a
--- /dev/null
+++ b/axios/ScreenSystem/InputAction.cs
@@ -0,0 +1,96 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// InputAction.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+using System;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Input;
+
+namespace GameStateManagement
+{
+ ///
+ /// Defines an action that is designated by some set of buttons and/or keys.
+ ///
+ /// The way actions work is that you define a set of buttons and keys that trigger the action. You can
+ /// then evaluate the action against an InputState which will test to see if any of the buttons or keys
+ /// are pressed by a player. You can also set a flag that indicates if the action only occurs once when
+ /// the buttons/keys are first pressed or whether the action should occur each frame.
+ ///
+ /// Using this InputAction class means that you can configure new actions based on keys and buttons
+ /// without having to directly modify the InputState type. This means more customization by your games
+ /// without having to change the core classes of Game State Management.
+ ///
+ public class InputAction
+ {
+ private readonly Buttons[] buttons;
+ private readonly Keys[] keys;
+ private readonly bool newPressOnly;
+
+ // These delegate types map to the methods on InputState. We use these to simplify the evalute method
+ // by allowing us to map the appropriate delegates and invoke them, rather than having two separate code paths.
+ private delegate bool ButtonPress(Buttons button, PlayerIndex? controllingPlayer, out PlayerIndex player);
+ private delegate bool KeyPress(Keys key, PlayerIndex? controllingPlayer, out PlayerIndex player);
+
+ ///
+ /// Initializes a new InputAction.
+ ///
+ /// An array of buttons that can trigger the action.
+ /// An array of keys that can trigger the action.
+ /// Whether the action only occurs on the first press of one of the buttons/keys,
+ /// false if it occurs each frame one of the buttons/keys is down.
+ public InputAction(Buttons[] buttons, Keys[] keys, bool newPressOnly)
+ {
+ // Store the buttons and keys. If the arrays are null, we create a 0 length array so we don't
+ // have to do null checks in the Evaluate method
+ this.buttons = buttons != null ? buttons.Clone() as Buttons[] : new Buttons[0];
+ this.keys = keys != null ? keys.Clone() as Keys[] : new Keys[0];
+
+ this.newPressOnly = newPressOnly;
+ }
+
+ ///
+ /// Evaluates the action against a given InputState.
+ ///
+ /// The InputState to test for the action.
+ /// The player to test, or null to allow any player.
+ /// If controllingPlayer is null, this is the player that performed the action.
+ /// True if the action occurred, false otherwise.
+ public bool Evaluate(InputState state, PlayerIndex? controllingPlayer, out PlayerIndex player)
+ {
+ // Figure out which delegate methods to map from the state which takes care of our "newPressOnly" logic
+ ButtonPress buttonTest;
+ KeyPress keyTest;
+ if (newPressOnly)
+ {
+ buttonTest = state.IsNewButtonPress;
+ keyTest = state.IsNewKeyPress;
+ }
+ else
+ {
+ buttonTest = state.IsButtonPressed;
+ keyTest = state.IsKeyPressed;
+ }
+
+ // Now we simply need to invoke the appropriate methods for each button and key in our collections
+ foreach (Buttons button in buttons)
+ {
+ if (buttonTest(button, controllingPlayer, out player))
+ return true;
+ }
+ foreach (Keys key in keys)
+ {
+ if (keyTest(key, controllingPlayer, out player))
+ return true;
+ }
+
+ // If we got here, the action is not matched
+ player = PlayerIndex.One;
+ return false;
+ }
+ }
+}
diff --git a/axios/ScreenSystem/InputState.cs b/axios/ScreenSystem/InputState.cs
new file mode 100644
index 0000000..1446751
--- /dev/null
+++ b/axios/ScreenSystem/InputState.cs
@@ -0,0 +1,233 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// InputState.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+using System.Collections.Generic;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Input;
+using Microsoft.Xna.Framework.Input.Touch;
+using FarseerPhysics.SamplesFramework;
+
+namespace GameStateManagement
+{
+ ///
+ /// Helper for reading input from keyboard, gamepad, and touch input. This class
+ /// tracks both the current and previous state of the input devices, and implements
+ /// query methods for high level input actions such as "move up through the menu"
+ /// or "pause the game".
+ ///
+ public class InputState
+ {
+ public const int MaxInputs = 4;
+
+ public readonly KeyboardState[] CurrentKeyboardStates;
+ public readonly GamePadState[] CurrentGamePadStates;
+
+ public readonly KeyboardState[] LastKeyboardStates;
+ public readonly GamePadState[] LastGamePadStates;
+
+ public readonly bool[] GamePadWasConnected;
+
+ /*
+ * Needed for virtual stick on WP7
+ * -- Nathan Adams [adamsna@datanethost.net] - 4/12/2012
+ */
+ private GamePadState _currentVirtualState;
+ private GamePadState _lastVirtualState;
+ private bool _handleVirtualStick;
+ /*
+ * I didn't create an array for the virtual stick because there will only be one
+ * -- Nathan Adams [adamsna@datanethost.net] - 4/12/2012
+ */
+
+
+ /*
+ *
+ *
+ *
+ *
+ *
+ */
+ private Vector2 _cursor;
+ private bool _cursorIsValid;
+ private bool _cursorIsVisible;
+ private bool _cursorMoved;
+ private Sprite _cursorSprite;
+
+#if WINDOWS_PHONE
+ private VirtualStick _phoneStick;
+ private VirtualButton _phoneA;
+ private VirtualButton _phoneB;
+#endif
+
+ public TouchCollection TouchState;
+
+ public readonly List Gestures = new List();
+
+
+ ///
+ /// Constructs a new input state.
+ ///
+ public InputState()
+ {
+ CurrentKeyboardStates = new KeyboardState[MaxInputs];
+ CurrentGamePadStates = new GamePadState[MaxInputs];
+
+ LastKeyboardStates = new KeyboardState[MaxInputs];
+ LastGamePadStates = new GamePadState[MaxInputs];
+
+ GamePadWasConnected = new bool[MaxInputs];
+ }
+
+ ///
+ /// Reads the latest state user input.
+ ///
+ public void Update()
+ {
+ for (int i = 0; i < MaxInputs; i++)
+ {
+ LastKeyboardStates[i] = CurrentKeyboardStates[i];
+ LastGamePadStates[i] = CurrentGamePadStates[i];
+
+ CurrentKeyboardStates[i] = Keyboard.GetState((PlayerIndex)i);
+ CurrentGamePadStates[i] = GamePad.GetState((PlayerIndex)i);
+
+ // Keep track of whether a gamepad has ever been
+ // connected, so we can detect if it is unplugged.
+ if (CurrentGamePadStates[i].IsConnected)
+ {
+ GamePadWasConnected[i] = true;
+ }
+ }
+
+ // Get the raw touch state from the TouchPanel
+ TouchState = TouchPanel.GetState();
+
+ // Read in any detected gestures into our list for the screens to later process
+ Gestures.Clear();
+ while (TouchPanel.IsGestureAvailable)
+ {
+ Gestures.Add(TouchPanel.ReadGesture());
+ }
+ }
+
+
+ ///
+ /// Helper for checking if a key was pressed during this update. The
+ /// controllingPlayer parameter specifies which player to read input for.
+ /// If this is null, it will accept input from any player. When a keypress
+ /// is detected, the output playerIndex reports which player pressed it.
+ ///
+ public bool IsKeyPressed(Keys key, PlayerIndex? controllingPlayer, out PlayerIndex playerIndex)
+ {
+ if (controllingPlayer.HasValue)
+ {
+ // Read input from the specified player.
+ playerIndex = controllingPlayer.Value;
+
+ int i = (int)playerIndex;
+
+ return CurrentKeyboardStates[i].IsKeyDown(key);
+ }
+ else
+ {
+ // Accept input from any player.
+ return (IsKeyPressed(key, PlayerIndex.One, out playerIndex) ||
+ IsKeyPressed(key, PlayerIndex.Two, out playerIndex) ||
+ IsKeyPressed(key, PlayerIndex.Three, out playerIndex) ||
+ IsKeyPressed(key, PlayerIndex.Four, out playerIndex));
+ }
+ }
+
+
+ ///
+ /// Helper for checking if a button was pressed during this update.
+ /// The controllingPlayer parameter specifies which player to read input for.
+ /// If this is null, it will accept input from any player. When a button press
+ /// is detected, the output playerIndex reports which player pressed it.
+ ///
+ public bool IsButtonPressed(Buttons button, PlayerIndex? controllingPlayer, out PlayerIndex playerIndex)
+ {
+ if (controllingPlayer.HasValue)
+ {
+ // Read input from the specified player.
+ playerIndex = controllingPlayer.Value;
+
+ int i = (int)playerIndex;
+
+ return CurrentGamePadStates[i].IsButtonDown(button);
+ }
+ else
+ {
+ // Accept input from any player.
+ return (IsButtonPressed(button, PlayerIndex.One, out playerIndex) ||
+ IsButtonPressed(button, PlayerIndex.Two, out playerIndex) ||
+ IsButtonPressed(button, PlayerIndex.Three, out playerIndex) ||
+ IsButtonPressed(button, PlayerIndex.Four, out playerIndex));
+ }
+ }
+
+
+ ///
+ /// Helper for checking if a key was newly pressed during this update. The
+ /// controllingPlayer parameter specifies which player to read input for.
+ /// If this is null, it will accept input from any player. When a keypress
+ /// is detected, the output playerIndex reports which player pressed it.
+ ///
+ public bool IsNewKeyPress(Keys key, PlayerIndex? controllingPlayer, out PlayerIndex playerIndex)
+ {
+ if (controllingPlayer.HasValue)
+ {
+ // Read input from the specified player.
+ playerIndex = controllingPlayer.Value;
+
+ int i = (int)playerIndex;
+
+ return (CurrentKeyboardStates[i].IsKeyDown(key) &&
+ LastKeyboardStates[i].IsKeyUp(key));
+ }
+ else
+ {
+ // Accept input from any player.
+ return (IsNewKeyPress(key, PlayerIndex.One, out playerIndex) ||
+ IsNewKeyPress(key, PlayerIndex.Two, out playerIndex) ||
+ IsNewKeyPress(key, PlayerIndex.Three, out playerIndex) ||
+ IsNewKeyPress(key, PlayerIndex.Four, out playerIndex));
+ }
+ }
+
+
+ ///
+ /// Helper for checking if a button was newly pressed during this update.
+ /// The controllingPlayer parameter specifies which player to read input for.
+ /// If this is null, it will accept input from any player. When a button press
+ /// is detected, the output playerIndex reports which player pressed it.
+ ///
+ public bool IsNewButtonPress(Buttons button, PlayerIndex? controllingPlayer, out PlayerIndex playerIndex)
+ {
+ if (controllingPlayer.HasValue)
+ {
+ // Read input from the specified player.
+ playerIndex = controllingPlayer.Value;
+
+ int i = (int)playerIndex;
+
+ return (CurrentGamePadStates[i].IsButtonDown(button) &&
+ LastGamePadStates[i].IsButtonUp(button));
+ }
+ else
+ {
+ // Accept input from any player.
+ return (IsNewButtonPress(button, PlayerIndex.One, out playerIndex) ||
+ IsNewButtonPress(button, PlayerIndex.Two, out playerIndex) ||
+ IsNewButtonPress(button, PlayerIndex.Three, out playerIndex) ||
+ IsNewButtonPress(button, PlayerIndex.Four, out playerIndex));
+ }
+ }
+ }
+}
diff --git a/axios/ScreenSystem/LoadingScreen.cs b/axios/ScreenSystem/LoadingScreen.cs
new file mode 100644
index 0000000..0d5cf24
--- /dev/null
+++ b/axios/ScreenSystem/LoadingScreen.cs
@@ -0,0 +1,163 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// LoadingScreen.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.Graphics;
+using GameStateManagement;
+#endregion
+
+namespace GameStateManagement
+{
+ ///
+ /// The loading screen coordinates transitions between the menu system and the
+ /// game itself. Normally one screen will transition off at the same time as
+ /// the next screen is transitioning on, but for larger transitions that can
+ /// take a longer time to load their data, we want the menu system to be entirely
+ /// gone before we start loading the game. This is done as follows:
+ ///
+ /// - Tell all the existing screens to transition off.
+ /// - Activate a loading screen, which will transition on at the same time.
+ /// - The loading screen watches the state of the previous screens.
+ /// - When it sees they have finished transitioning off, it activates the real
+ /// next screen, which may take a long time to load its data. The loading
+ /// screen will be the only thing displayed while this load is taking place.
+ ///
+ class LoadingScreen : GameScreen
+ {
+ #region Fields
+
+ bool loadingIsSlow;
+ bool otherScreensAreGone;
+
+ GameScreen[] screensToLoad;
+
+ #endregion
+
+ #region Initialization
+
+
+ ///
+ /// The constructor is private: loading screens should
+ /// be activated via the static Load method instead.
+ ///
+ private LoadingScreen(ScreenManager screenManager, bool loadingIsSlow,
+ GameScreen[] screensToLoad)
+ {
+ this.loadingIsSlow = loadingIsSlow;
+ this.screensToLoad = screensToLoad;
+
+ TransitionOnTime = TimeSpan.FromSeconds(0.5);
+ }
+
+
+ ///
+ /// Activates the loading screen.
+ ///
+ public static void Load(ScreenManager screenManager, bool loadingIsSlow,
+ PlayerIndex? controllingPlayer,
+ params GameScreen[] screensToLoad)
+ {
+ // Tell all the current screens to transition off.
+ foreach (GameScreen screen in screenManager.GetScreens())
+ screen.ExitScreen();
+
+ // Create and activate the loading screen.
+ LoadingScreen loadingScreen = new LoadingScreen(screenManager,
+ loadingIsSlow,
+ screensToLoad);
+
+ screenManager.AddScreen(loadingScreen, controllingPlayer);
+ }
+
+
+ #endregion
+
+ #region Update and Draw
+
+
+ ///
+ /// Updates the loading screen.
+ ///
+ public override void Update(GameTime gameTime, bool otherScreenHasFocus,
+ bool coveredByOtherScreen)
+ {
+ base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
+
+ // If all the previous screens have finished transitioning
+ // off, it is time to actually perform the load.
+ if (otherScreensAreGone)
+ {
+ ScreenManager.RemoveScreen(this);
+
+ foreach (GameScreen screen in screensToLoad)
+ {
+ if (screen != null)
+ {
+ ScreenManager.AddScreen(screen, ControllingPlayer);
+ }
+ }
+
+ // Once the load has finished, we use ResetElapsedTime to tell
+ // the game timing mechanism that we have just finished a very
+ // long frame, and that it should not try to catch up.
+ ScreenManager.Game.ResetElapsedTime();
+ }
+ }
+
+
+ ///
+ /// Draws the loading screen.
+ ///
+ public override void Draw(GameTime gameTime)
+ {
+ // If we are the only active screen, that means all the previous screens
+ // must have finished transitioning off. We check for this in the Draw
+ // method, rather than in Update, because it isn't enough just for the
+ // screens to be gone: in order for the transition to look good we must
+ // have actually drawn a frame without them before we perform the load.
+ if ((ScreenState == ScreenState.Active) &&
+ (ScreenManager.GetScreens().Length == 1))
+ {
+ otherScreensAreGone = true;
+ }
+
+ // The gameplay screen takes a while to load, so we display a loading
+ // message while that is going on, but the menus load very quickly, and
+ // it would look silly if we flashed this up for just a fraction of a
+ // second while returning from the game to the menus. This parameter
+ // tells us how long the loading is going to take, so we know whether
+ // to bother drawing the message.
+ if (loadingIsSlow)
+ {
+ SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
+ SpriteFont font = ScreenManager.Font;
+
+ const string message = "Loading...";
+
+ // Center the 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;
+
+ Color color = Color.White * TransitionAlpha;
+
+ // Draw the text.
+ spriteBatch.Begin();
+ spriteBatch.DrawString(font, message, textPosition, color);
+ spriteBatch.End();
+ }
+ }
+
+
+ #endregion
+ }
+}
diff --git a/axios/ScreenSystem/MainMenuScreen.cs b/axios/ScreenSystem/MainMenuScreen.cs
new file mode 100644
index 0000000..7a60d8e
--- /dev/null
+++ b/axios/ScreenSystem/MainMenuScreen.cs
@@ -0,0 +1,98 @@
+#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;
+#endregion
+
+namespace GameStateManagement
+{
+ ///
+ /// The main menu screen is the first thing displayed when the game starts up.
+ ///
+ class MainMenuScreen : MenuScreen
+ {
+ #region Initialization
+
+
+ ///
+ /// Constructor fills in the menu contents.
+ ///
+ public MainMenuScreen()
+ : base("Main Menu")
+ {
+ // Create our menu entries.
+ MenuEntry playGameMenuEntry = new MenuEntry("Play Game");
+ MenuEntry optionsMenuEntry = new MenuEntry("Options");
+ MenuEntry exitMenuEntry = new MenuEntry("Exit");
+
+ // Hook up menu event handlers.
+ playGameMenuEntry.Selected += PlayGameMenuEntrySelected;
+ optionsMenuEntry.Selected += OptionsMenuEntrySelected;
+ exitMenuEntry.Selected += OnCancel;
+
+ // Add entries to the menu.
+ MenuEntries.Add(playGameMenuEntry);
+ MenuEntries.Add(optionsMenuEntry);
+ MenuEntries.Add(exitMenuEntry);
+ }
+
+
+ #endregion
+
+ #region Handle Input
+
+
+ ///
+ /// Event handler for when the Play Game menu entry is selected.
+ ///
+ void PlayGameMenuEntrySelected(object sender, PlayerIndexEventArgs e)
+ {
+ LoadingScreen.Load(ScreenManager, true, e.PlayerIndex,
+ new GameplayScreen());
+ }
+
+
+ ///
+ /// Event handler for when the Options menu entry is selected.
+ ///
+ void OptionsMenuEntrySelected(object sender, PlayerIndexEventArgs e)
+ {
+ ScreenManager.AddScreen(new OptionsMenuScreen(), e.PlayerIndex);
+ }
+
+
+ ///
+ /// When the user cancels the main menu, ask if they want to exit the sample.
+ ///
+ protected override void OnCancel(PlayerIndex playerIndex)
+ {
+ const string message = "Are you sure you want to exit this sample?";
+
+ MessageBoxScreen confirmExitMessageBox = new MessageBoxScreen(message);
+
+ confirmExitMessageBox.Accepted += ConfirmExitMessageBoxAccepted;
+
+ ScreenManager.AddScreen(confirmExitMessageBox, playerIndex);
+ }
+
+
+ ///
+ /// Event handler for when the user selects ok on the "are you sure
+ /// you want to exit" message box.
+ ///
+ void ConfirmExitMessageBoxAccepted(object sender, PlayerIndexEventArgs e)
+ {
+ ScreenManager.Game.Exit();
+ }
+
+
+ #endregion
+ }
+}
diff --git a/axios/ScreenSystem/OptionsMenuScreen.cs b/axios/ScreenSystem/OptionsMenuScreen.cs
new file mode 100644
index 0000000..8e549db
--- /dev/null
+++ b/axios/ScreenSystem/OptionsMenuScreen.cs
@@ -0,0 +1,149 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// OptionsMenuScreen.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using Microsoft.Xna.Framework;
+#endregion
+
+namespace GameStateManagement
+{
+ ///
+ /// The options screen is brought up over the top of the main menu
+ /// screen, and gives the user a chance to configure the game
+ /// in various hopefully useful ways.
+ ///
+ class OptionsMenuScreen : MenuScreen
+ {
+ #region Fields
+
+ MenuEntry ungulateMenuEntry;
+ MenuEntry languageMenuEntry;
+ MenuEntry frobnicateMenuEntry;
+ MenuEntry elfMenuEntry;
+
+ enum Ungulate
+ {
+ BactrianCamel,
+ Dromedary,
+ Llama,
+ }
+
+ static Ungulate currentUngulate = Ungulate.Dromedary;
+
+ static string[] languages = { "C#", "French", "Deoxyribonucleic acid" };
+ static int currentLanguage = 0;
+
+ static bool frobnicate = true;
+
+ static int elf = 23;
+
+ #endregion
+
+ #region Initialization
+
+
+ ///
+ /// Constructor.
+ ///
+ public OptionsMenuScreen()
+ : base("Options")
+ {
+ // Create our menu entries.
+ ungulateMenuEntry = new MenuEntry(string.Empty);
+ languageMenuEntry = new MenuEntry(string.Empty);
+ frobnicateMenuEntry = new MenuEntry(string.Empty);
+ elfMenuEntry = new MenuEntry(string.Empty);
+
+ SetMenuEntryText();
+
+ MenuEntry back = new MenuEntry("Back");
+
+ // Hook up menu event handlers.
+ ungulateMenuEntry.Selected += UngulateMenuEntrySelected;
+ languageMenuEntry.Selected += LanguageMenuEntrySelected;
+ frobnicateMenuEntry.Selected += FrobnicateMenuEntrySelected;
+ elfMenuEntry.Selected += ElfMenuEntrySelected;
+ back.Selected += OnCancel;
+
+ // Add entries to the menu.
+ MenuEntries.Add(ungulateMenuEntry);
+ MenuEntries.Add(languageMenuEntry);
+ MenuEntries.Add(frobnicateMenuEntry);
+ MenuEntries.Add(elfMenuEntry);
+ MenuEntries.Add(back);
+ }
+
+
+ ///
+ /// Fills in the latest values for the options screen menu text.
+ ///
+ void SetMenuEntryText()
+ {
+ ungulateMenuEntry.Text = "Preferred ungulate: " + currentUngulate;
+ languageMenuEntry.Text = "Language: " + languages[currentLanguage];
+ frobnicateMenuEntry.Text = "Frobnicate: " + (frobnicate ? "on" : "off");
+ elfMenuEntry.Text = "elf: " + elf;
+ }
+
+
+ #endregion
+
+ #region Handle Input
+
+
+ ///
+ /// Event handler for when the Ungulate menu entry is selected.
+ ///
+ void UngulateMenuEntrySelected(object sender, PlayerIndexEventArgs e)
+ {
+ currentUngulate++;
+
+ if (currentUngulate > Ungulate.Llama)
+ currentUngulate = 0;
+
+ SetMenuEntryText();
+ }
+
+
+ ///
+ /// Event handler for when the Language menu entry is selected.
+ ///
+ void LanguageMenuEntrySelected(object sender, PlayerIndexEventArgs e)
+ {
+ currentLanguage = (currentLanguage + 1) % languages.Length;
+
+ SetMenuEntryText();
+ }
+
+
+ ///
+ /// Event handler for when the Frobnicate menu entry is selected.
+ ///
+ void FrobnicateMenuEntrySelected(object sender, PlayerIndexEventArgs e)
+ {
+ frobnicate = !frobnicate;
+
+ SetMenuEntryText();
+ }
+
+
+ ///
+ /// Event handler for when the Elf menu entry is selected.
+ ///
+ void ElfMenuEntrySelected(object sender, PlayerIndexEventArgs e)
+ {
+ elf++;
+
+ SetMenuEntryText();
+ }
+
+
+ #endregion
+ }
+}
diff --git a/axios/ScreenSystem/PauseMenuScreen.cs b/axios/ScreenSystem/PauseMenuScreen.cs
new file mode 100644
index 0000000..667ff71
--- /dev/null
+++ b/axios/ScreenSystem/PauseMenuScreen.cs
@@ -0,0 +1,79 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// PauseMenuScreen.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+#region Using Statements
+using Microsoft.Xna.Framework;
+#endregion
+
+namespace GameStateManagement
+{
+ ///
+ /// The pause menu comes up over the top of the game,
+ /// giving the player options to resume or quit.
+ ///
+ class PauseMenuScreen : MenuScreen
+ {
+ #region Initialization
+
+
+ ///
+ /// Constructor.
+ ///
+ public PauseMenuScreen()
+ : base("Paused")
+ {
+ // Create our menu entries.
+ MenuEntry resumeGameMenuEntry = new MenuEntry("Resume Game");
+ MenuEntry quitGameMenuEntry = new MenuEntry("Quit Game");
+
+ // Hook up menu event handlers.
+ resumeGameMenuEntry.Selected += OnCancel;
+ quitGameMenuEntry.Selected += QuitGameMenuEntrySelected;
+
+ // Add entries to the menu.
+ MenuEntries.Add(resumeGameMenuEntry);
+ MenuEntries.Add(quitGameMenuEntry);
+ }
+
+
+ #endregion
+
+ #region Handle Input
+
+
+ ///
+ /// Event handler for when the Quit Game menu entry is selected.
+ ///
+ void QuitGameMenuEntrySelected(object sender, PlayerIndexEventArgs e)
+ {
+ const string message = "Are you sure you want to quit this game?";
+
+ MessageBoxScreen confirmQuitMessageBox = new MessageBoxScreen(message);
+
+ confirmQuitMessageBox.Accepted += ConfirmQuitMessageBoxAccepted;
+
+ ScreenManager.AddScreen(confirmQuitMessageBox, ControllingPlayer);
+ }
+
+
+ ///
+ /// Event handler for when the user selects ok on the "are you sure
+ /// you want to quit" message box. This uses the loading screen to
+ /// transition from the game back to the main menu screen.
+ ///
+ void ConfirmQuitMessageBoxAccepted(object sender, PlayerIndexEventArgs e)
+ {
+ LoadingScreen.Load(ScreenManager, false, null, new BackgroundScreen(),
+ new MainMenuScreen());
+ }
+
+
+ #endregion
+ }
+}
diff --git a/axios/ScreenSystem/PhoneMainMenuScreen.cs b/axios/ScreenSystem/PhoneMainMenuScreen.cs
new file mode 100644
index 0000000..3afcd8b
--- /dev/null
+++ b/axios/ScreenSystem/PhoneMainMenuScreen.cs
@@ -0,0 +1,65 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// PhoneMainMenuScreen.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+using System;
+using GameStateManagement;
+using Microsoft.Xna.Framework;
+
+namespace GameStateManagement
+{
+ class PhoneMainMenuScreen : PhoneMenuScreen
+ {
+ public PhoneMainMenuScreen()
+ : base("Main Menu")
+ {
+ // Create a button to start the game
+ Button playButton = new Button("Play");
+ playButton.Tapped += playButton_Tapped;
+ MenuButtons.Add(playButton);
+
+ // Create two buttons to toggle sound effects and music. This sample just shows one way
+ // of making and using these buttons; it doesn't actually have sound effects or music
+ BooleanButton sfxButton = new BooleanButton("Sound Effects", true);
+ sfxButton.Tapped += sfxButton_Tapped;
+ MenuButtons.Add(sfxButton);
+
+ BooleanButton musicButton = new BooleanButton("Music", true);
+ musicButton.Tapped += musicButton_Tapped;
+ MenuButtons.Add(musicButton);
+ }
+
+ void playButton_Tapped(object sender, EventArgs e)
+ {
+ // When the "Play" button is tapped, we load the GameplayScreen
+ LoadingScreen.Load(ScreenManager, true, PlayerIndex.One, new GameplayScreen());
+ }
+
+ void sfxButton_Tapped(object sender, EventArgs e)
+ {
+ BooleanButton button = sender as BooleanButton;
+
+ // In a real game, you'd want to store away the value of
+ // the button to turn off sounds here. :)
+ }
+
+ void musicButton_Tapped(object sender, EventArgs e)
+ {
+ BooleanButton button = sender as BooleanButton;
+
+ // In a real game, you'd want to store away the value of
+ // the button to turn off music here. :)
+ }
+
+ protected override void OnCancel()
+ {
+ ScreenManager.Game.Exit();
+ base.OnCancel();
+ }
+ }
+}
diff --git a/axios/ScreenSystem/PhoneMenuScreen.cs b/axios/ScreenSystem/PhoneMenuScreen.cs
new file mode 100644
index 0000000..85c88ae
--- /dev/null
+++ b/axios/ScreenSystem/PhoneMenuScreen.cs
@@ -0,0 +1,149 @@
+#region File Description
+//-----------------------------------------------------------------------------
+// PhoneMenuScreen.cs
+//
+// Microsoft XNA Community Game Platform
+// Copyright (C) Microsoft Corporation. All rights reserved.
+//-----------------------------------------------------------------------------
+#endregion
+
+using System;
+using System.Collections.Generic;
+using GameStateManagement;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Graphics;
+using Microsoft.Xna.Framework.Input;
+using Microsoft.Xna.Framework.Input.Touch;
+
+namespace GameStateManagement
+{
+ ///
+ /// Provides a basic base screen for menus on Windows Phone leveraging the Button class.
+ ///
+ class PhoneMenuScreen : GameScreen
+ {
+ List