Przeglądaj źródła

[CatapultNetWars] Scale Screen depending of device, from base screen.

Dominique Louis 3 tygodni temu
rodzic
commit
bcef062f47

+ 3 - 2
CatapultNetWars/Core/CatapultGame.cs

@@ -27,6 +27,7 @@ namespace CatapultGame
 	{
 		GraphicsDeviceManager graphicsDeviceManager;
 		ScreenManager screenManager;
+		public ScreenManager ScreenManager { get => screenManager; set => screenManager = value; }
 
 		// By preloading any assets used by UI rendering, we avoid framerate glitches
 		// when they suddenly need to be loaded in the middle of a menu transition.
@@ -45,8 +46,8 @@ namespace CatapultGame
 			graphicsDeviceManager = new GraphicsDeviceManager(this);
 			//graphics.SynchronizeWithVerticalRetrace = false;
 
-			graphicsDeviceManager.PreferredBackBufferHeight = 480;
-			graphicsDeviceManager.PreferredBackBufferWidth = 800;
+			graphicsDeviceManager.PreferredBackBufferWidth = ScreenManager.BASE_BUFFER_WIDTH;
+			graphicsDeviceManager.PreferredBackBufferHeight = ScreenManager.BASE_BUFFER_HEIGHT;
 
 			if (UIUtility.IsMobile)
 			{

+ 3 - 3
CatapultNetWars/Core/MessageDisplayComponent.cs

@@ -34,8 +34,7 @@ namespace CatapultGame
         static readonly TimeSpan showTime = TimeSpan.FromSeconds(5);
         static readonly TimeSpan fadeOutTime = TimeSpan.FromSeconds(0.5);
 
-
-
+        CatapultGame game;
 
         /// <summary>
         /// Constructs a new message display component.
@@ -43,6 +42,7 @@ namespace CatapultGame
         public MessageDisplayComponent(Game game)
             : base(game)
         {
+            this.game = game as CatapultGame;
             // Register ourselves to implement the IMessageDisplay service.
             game.Services.AddService(typeof(IMessageDisplay), this);
         }
@@ -122,7 +122,7 @@ namespace CatapultGame
 
                 Vector2 position = new Vector2(GraphicsDevice.Viewport.Width - 100, 0);
 
-                spriteBatch.Begin();
+                spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, game.ScreenManager.GlobalTransformation);
 
                 // Draw each message in turn.
                 foreach (NotificationMessage message in messages)

+ 1 - 1
CatapultNetWars/Core/Networking/LobbyScreen.cs

@@ -180,7 +180,7 @@ namespace CatapultGame
 			else
 				position.X += transitionOffset * 512;
 
-			spriteBatch.Begin();
+			spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, ScreenManager.GlobalTransformation);
 
 			// Draw all the gamers in the session.
 			int gamerCount = 0;

+ 1 - 1
CatapultNetWars/Core/Networking/NetworkBusyScreen.cs

@@ -161,7 +161,7 @@ namespace CatapultGame
 			// Fade the popup alpha during transitions.
 			Color color = Color.White * TransitionAlpha;
 
-			spriteBatch.Begin();
+			spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, ScreenManager.GlobalTransformation);
 
 			// Draw the background rectangle.
 			spriteBatch.Draw(gradientTexture, backgroundRectangle, color);

+ 12 - 3
CatapultNetWars/Core/ScreenManager/GameScreen.cs

@@ -222,7 +222,10 @@ namespace CatapultGame
         /// <summary>
         /// Load graphics content for the screen.
         /// </summary>
-        public virtual void LoadContent() { }
+        public virtual void LoadContent()
+        {
+            ScreenManager.ScalePresentationArea();
+        }
 
 
         /// <summary>
@@ -283,6 +286,14 @@ namespace CatapultGame
                     screenState = ScreenState.Active;
                 }
             }
+
+            // Check if the back buffer size has changed (e.g., window resize).
+			if (ScreenManager.BackbufferHeight != ScreenManager.GraphicsDevice.PresentationParameters.BackBufferHeight
+				|| ScreenManager.BackbufferWidth != ScreenManager.GraphicsDevice.PresentationParameters.BackBufferWidth)
+			{
+				// Adjust the presentation area to match the new back buffer size.
+				ScreenManager.ScalePresentationArea();
+			}
         }
 
 
@@ -361,8 +372,6 @@ namespace CatapultGame
             }
         }
 
-
-
         /// <summary>
         /// A helper method which loads assets using the screen manager's
         /// associated game content loader.

+ 101 - 80
CatapultNetWars/Core/ScreenManager/InputState.cs

@@ -21,7 +21,6 @@ namespace CatapultGame
 	/// </summary>
 	public class InputState
 	{
-
 		public const int MaxInputs = 4;
 		public readonly KeyboardState[] CurrentKeyboardStates;
 		public readonly GamePadState[] CurrentGamePadStates;
@@ -31,16 +30,20 @@ namespace CatapultGame
 		public TouchCollection TouchState;
 		public MouseState CurrentMouseState;
 		public MouseState LastMouseState;
-		public readonly List<GestureSample> Gestures = new List<GestureSample> ();
-
-
+		public readonly List<GestureSample> Gestures = new List<GestureSample>();
 
+		Matrix inputTransformation;
+		readonly float baseBufferWidth;
+		readonly float baseBufferHeight;
 
 		/// <summary>
 		/// Constructs a new input state.
 		/// </summary>
-		public InputState ()
+		public InputState(float baseBufferWidth, float baseBufferHeight)
 		{
+			this.baseBufferWidth = baseBufferWidth;
+			this.baseBufferHeight = baseBufferHeight;
+
 			CurrentKeyboardStates = new KeyboardState[MaxInputs];
 			CurrentGamePadStates = new GamePadState[MaxInputs];
 
@@ -50,39 +53,38 @@ namespace CatapultGame
 			GamePadWasConnected = new bool[MaxInputs];
 		}
 
-
-
-
-
 		/// <summary>
 		/// Reads the latest state of the keyboard and gamepad.
 		/// </summary>
-		public void Update ()
+		public void Update()
 		{
-			for (int i = 0; i < MaxInputs; i++) {
-				LastKeyboardStates [i] = CurrentKeyboardStates [i];
-				LastGamePadStates [i] = CurrentGamePadStates [i];
+			for (int i = 0; i < MaxInputs; i++)
+			{
+				LastKeyboardStates[i] = CurrentKeyboardStates[i];
+				LastGamePadStates[i] = CurrentGamePadStates[i];
 
-				CurrentKeyboardStates [i] = Keyboard.GetState ();
-				CurrentGamePadStates [i] = GamePad.GetState ((PlayerIndex)i);
+				CurrentKeyboardStates[i] = Keyboard.GetState();
+				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;
+				if (CurrentGamePadStates[i].IsConnected)
+				{
+					GamePadWasConnected[i] = true;
 				}
 			}
 
-			TouchState = TouchPanel.GetState ();
+			TouchState = TouchPanel.GetState();
 
 			LastMouseState = CurrentMouseState;
-			CurrentMouseState = Mouse.GetState ();
+			CurrentMouseState = Mouse.GetState();
 
 			UpdateMouseStates();
 
-			Gestures.Clear ();
-			while (TouchPanel.IsGestureAvailable) {
-				Gestures.Add (TouchPanel.ReadGesture ());
+			Gestures.Clear();
+			while (TouchPanel.IsGestureAvailable)
+			{
+				Gestures.Add(TouchPanel.ReadGesture());
 			}
 		}
 
@@ -98,54 +100,61 @@ namespace CatapultGame
 
 		public MouseGestureType MouseGesture
 		{
-			get {
+			get
+			{
 				return mouseGestureType;
 			}
 		}
 
 		public Vector2 CurrentMousePosition
 		{
-			get {
+			get
+			{
 				return currentMousePosition;
 			}
 		}
 
 		public Vector2 PrevMousePosition
 		{
-			get {
+			get
+			{
 				return prevMousePosition;
 			}
 		}
 
 		public Vector2 MouseDelta
 		{
-			get {
+			get
+			{
 				return prevMousePosition - currentMousePosition;
 			}
 		}
 
 		public Vector2 MouseDragDelta
 		{
-			get {
+			get
+			{
 				return dragMouseStart - dragMouseEnd;
 			}
 		}
 
 		public Vector2 MouseDragStartPosition
 		{
-			get {
+			get
+			{
 				return dragMouseStart;
 			}
 		}
 
 		public Vector2 MouseDragEndPosition
 		{
-			get {
+			get
+			{
 				return dragMouseEnd;
 			}
 		}
 
-		void UpdateMouseStates ()
+		void UpdateMouseStates()
 		{
 			currentMousePosition.X = CurrentMouseState.X;
 			currentMousePosition.Y = CurrentMouseState.Y;
@@ -165,7 +174,8 @@ namespace CatapultGame
 			// If we were dragging and the left mouse button was released
 			// then we are no longer dragging and need to throw the banana.
 			if (CurrentMouseState.LeftButton == ButtonState.Released &&
-					dragging) {
+					dragging)
+			{
 
 				leftMouseDown = false;
 				dragging = false;
@@ -179,7 +189,8 @@ namespace CatapultGame
 
 			// Let's set the left mouse down and the mouse origin
 			if (!leftMouseDown && CurrentMouseState.LeftButton == ButtonState.Pressed &&
-					!CurrentMouseState.Equals (LastMouseState)) {
+					!CurrentMouseState.Equals(LastMouseState))
+			{
 				//Console.WriteLine ("left down");
 				leftMouseDown = true;
 				dragComplete = false;
@@ -187,18 +198,21 @@ namespace CatapultGame
 			}
 
 			if (leftMouseDown && CurrentMouseState.LeftButton == ButtonState.Released &&
-					!CurrentMouseState.Equals (LastMouseState)) {
+					!CurrentMouseState.Equals(LastMouseState))
+			{
 				leftMouseDown = false;
 				mouseGestureType |= MouseGestureType.LeftClick;
 			}
 
 			// Here we test the distance and if over the threshold then we set the dragging to true
 			//  Current threshold is 5 pixels.
-			if (leftMouseDown && !dragging) {
+			if (leftMouseDown && !dragging)
+			{
 
 				Vector2 delta = dragMouseStart - currentMousePosition;
 
-				if (delta.Length() > dragThreshold) {
+				if (delta.Length() > dragThreshold)
+				{
 					dragging = true;
 					dragMouseStart = currentMousePosition;
 					mouseGestureType = mouseGestureType | MouseGestureType.FreeDrag;
@@ -215,123 +229,130 @@ namespace CatapultGame
 		/// If this is null, it will accept input from any player. When a keypress
 		/// is detected, the output playerIndex reports which player pressed it.
 		/// </summary>
-		public bool IsNewKeyPress (Keys key, PlayerIndex? controllingPlayer, out PlayerIndex playerIndex)
+		public bool IsNewKeyPress(Keys key, PlayerIndex? controllingPlayer, out PlayerIndex playerIndex)
 		{
-			if (controllingPlayer.HasValue) {
+			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 {
+				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));
+				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));
 			}
 		}
 
-
 		/// <summary>
 		/// 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.
 		/// </summary>
-		public bool IsNewButtonPress (Buttons button, PlayerIndex? controllingPlayer, out PlayerIndex playerIndex)
+		public bool IsNewButtonPress(Buttons button, PlayerIndex? controllingPlayer, out PlayerIndex playerIndex)
 		{
-			if (controllingPlayer.HasValue) {
+			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 {
+				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));
+				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));
 			}
 		}
 
-
 		/// <summary>
 		/// Checks for a "menu select" input action.
 		/// The controllingPlayer parameter specifies which player to read input for.
 		/// If this is null, it will accept input from any player. When the action
 		/// is detected, the output playerIndex reports which player pressed it.
 		/// </summary>
-		public bool IsMenuSelect (PlayerIndex? controllingPlayer, out PlayerIndex playerIndex)
+		public bool IsMenuSelect(PlayerIndex? controllingPlayer, out PlayerIndex playerIndex)
 		{
-			return IsNewKeyPress (Keys.Space, controllingPlayer, out playerIndex) ||
-						IsNewKeyPress (Keys.Enter, controllingPlayer, out playerIndex) ||
-						IsNewButtonPress (Buttons.A, controllingPlayer, out playerIndex) ||
-						IsNewButtonPress (Buttons.Start, controllingPlayer, out playerIndex);
+			return IsNewKeyPress(Keys.Space, controllingPlayer, out playerIndex) ||
+						IsNewKeyPress(Keys.Enter, controllingPlayer, out playerIndex) ||
+						IsNewButtonPress(Buttons.A, controllingPlayer, out playerIndex) ||
+						IsNewButtonPress(Buttons.Start, controllingPlayer, out playerIndex);
 		}
 
-
 		/// <summary>
 		/// Checks for a "menu cancel" input action.
 		/// The controllingPlayer parameter specifies which player to read input for.
 		/// If this is null, it will accept input from any player. When the action
 		/// is detected, the output playerIndex reports which player pressed it.
 		/// </summary>
-		public bool IsMenuCancel (PlayerIndex? controllingPlayer, out PlayerIndex playerIndex)
+		public bool IsMenuCancel(PlayerIndex? controllingPlayer, out PlayerIndex playerIndex)
 		{
-			return IsNewKeyPress (Keys.Escape, controllingPlayer, out playerIndex) ||
-						IsNewButtonPress (Buttons.B, controllingPlayer, out playerIndex) ||
-						IsNewButtonPress (Buttons.Back, controllingPlayer, out playerIndex);
+			return IsNewKeyPress(Keys.Escape, controllingPlayer, out playerIndex) ||
+						IsNewButtonPress(Buttons.B, controllingPlayer, out playerIndex) ||
+						IsNewButtonPress(Buttons.Back, controllingPlayer, out playerIndex);
 		}
 
-
 		/// <summary>
 		/// Checks for a "menu up" input action.
 		/// The controllingPlayer parameter specifies which player to read
 		/// input for. If this is null, it will accept input from any player.
 		/// </summary>
-		public bool IsMenuUp (PlayerIndex? controllingPlayer)
+		public bool IsMenuUp(PlayerIndex? controllingPlayer)
 		{
 			PlayerIndex playerIndex;
 
-			return IsNewKeyPress (Keys.Up, controllingPlayer, out playerIndex) ||
-						IsNewButtonPress (Buttons.DPadUp, controllingPlayer, out playerIndex) ||
-						IsNewButtonPress (Buttons.LeftThumbstickUp, controllingPlayer, out playerIndex);
+			return IsNewKeyPress(Keys.Up, controllingPlayer, out playerIndex) ||
+						IsNewButtonPress(Buttons.DPadUp, controllingPlayer, out playerIndex) ||
+						IsNewButtonPress(Buttons.LeftThumbstickUp, controllingPlayer, out playerIndex);
 		}
 
-
 		/// <summary>
 		/// Checks for a "menu down" input action.
 		/// The controllingPlayer parameter specifies which player to read
 		/// input for. If this is null, it will accept input from any player.
 		/// </summary>
-		public bool IsMenuDown (PlayerIndex? controllingPlayer)
+		public bool IsMenuDown(PlayerIndex? controllingPlayer)
 		{
 			PlayerIndex playerIndex;
 
-			return IsNewKeyPress (Keys.Down, controllingPlayer, out playerIndex) ||
-						IsNewButtonPress (Buttons.DPadDown, controllingPlayer, out playerIndex) ||
-						IsNewButtonPress (Buttons.LeftThumbstickDown, controllingPlayer, out playerIndex);
+			return IsNewKeyPress(Keys.Down, controllingPlayer, out playerIndex) ||
+						IsNewButtonPress(Buttons.DPadDown, controllingPlayer, out playerIndex) ||
+						IsNewButtonPress(Buttons.LeftThumbstickDown, controllingPlayer, out playerIndex);
 		}
 
-
 		/// <summary>
 		/// Checks for a "pause the game" input action.
 		/// The controllingPlayer parameter specifies which player to read
 		/// input for. If this is null, it will accept input from any player.
 		/// </summary>
-		public bool IsPauseGame (PlayerIndex? controllingPlayer)
+		public bool IsPauseGame(PlayerIndex? controllingPlayer)
 		{
 			PlayerIndex playerIndex;
 
-			return IsNewKeyPress (Keys.Escape, controllingPlayer, out playerIndex) ||
-						IsNewButtonPress (Buttons.Back, controllingPlayer, out playerIndex) ||
-						IsNewButtonPress (Buttons.Start, controllingPlayer, out playerIndex);
+			return IsNewKeyPress(Keys.Escape, controllingPlayer, out playerIndex) ||
+						IsNewButtonPress(Buttons.Back, controllingPlayer, out playerIndex) ||
+						IsNewButtonPress(Buttons.Start, controllingPlayer, out playerIndex);
 		}
 
-
+		/// <summary>
+		/// Updates the matrix used to transform input coordinates.
+		/// </summary>
+		/// <param name="inputTransformation">The transformation matrix to apply.</param>
+		public void UpdateInputTransformation(Matrix inputTransformation)
+		{
+			this.inputTransformation = inputTransformation;
+		}
 	}
-}
+}

+ 72 - 87
CatapultNetWars/Core/ScreenManager/MenuScreen.cs

@@ -20,7 +20,6 @@ namespace CatapultGame
     /// </summary>
     abstract class MenuScreen : GameScreen
     {
-
         // the number of pixels to pad above and below menu entries for touch input
         //const int menuEntryPadding = 35;
         const int menuEntryPadding = 10;
@@ -29,9 +28,6 @@ namespace CatapultGame
         int selectedEntry = 0;
         string menuTitle;
 
-
-
-
         /// <summary>
         /// Gets the list of menu entries, so derived classes can add
         /// or change the menu contents.
@@ -41,10 +37,6 @@ namespace CatapultGame
             get { return menuEntries; }
         }
 
-
-
-
-
         /// <summary>
         /// Constructor.
         /// </summary>
@@ -59,9 +51,6 @@ namespace CatapultGame
             TransitionOffTime = TimeSpan.FromSeconds(0.5);
         }
 
-
-
-
         /// <summary>
         /// Allows the screen to create the hit bounds for a particular menu entry.
         /// </summary>
@@ -89,56 +78,61 @@ namespace CatapultGame
                 OnCancel(player);
             }
 
-			if (input.IsMenuDown(ControllingPlayer)) {
-				if (selectedEntry < menuEntries.Count - 1)
-					selectedEntry += 1;
-			}
-
-			if (input.IsMenuUp(ControllingPlayer)) {
-				if (selectedEntry > 0)
-					selectedEntry -= 1;
-			}
-
-			if (input.IsMenuSelect(ControllingPlayer, out player)) {
-				menuEntries[selectedEntry].OnSelectEntry(player);
-			}
-
-			if (input.MouseGesture.HasFlag(MouseGestureType.LeftClick)) {
-
-				Point clickLocation = new Point((int)input.CurrentMousePosition.X, (int)input.CurrentMousePosition.Y);
-				// iterate the entries to see if any were tapped
-				for (int i = 0; i < menuEntries.Count; i++)
-				{
-					MenuEntry menuEntry = menuEntries[i];
-
-					if (GetMenuEntryHitBounds(menuEntry).Contains(clickLocation))
-					{
-						// select the entry. since gestures are only available on Windows Phone,
-						// we can safely pass PlayerIndex.One to all entries since there is only
-						// one player on Windows Phone.
-						OnSelectEntry(i, PlayerIndex.One);
-					}
-				}
-			}
-
-			if (input.MouseGesture.HasFlag(MouseGestureType.Move)) {
-
-				Point clickLocation = new Point((int)input.CurrentMousePosition.X, (int)input.CurrentMousePosition.Y);
-				// iterate the entries to see if any were tapped
-				for (int i = 0; i < menuEntries.Count; i++)
-				{
-					MenuEntry menuEntry = menuEntries[i];
-
-					if (GetMenuEntryHitBounds(menuEntry).Contains(clickLocation))
-					{
-						// select the entry. since gestures are only available on Windows Phone,
-						// we can safely pass PlayerIndex.One to all entries since there is only
-						// one player on Windows Phone.
-						//OnSelectEntry(i, PlayerIndex.One);
-						selectedEntry = i;
-					}
-				}
-			}
+            if (input.IsMenuDown(ControllingPlayer))
+            {
+                if (selectedEntry < menuEntries.Count - 1)
+                    selectedEntry += 1;
+            }
+
+            if (input.IsMenuUp(ControllingPlayer))
+            {
+                if (selectedEntry > 0)
+                    selectedEntry -= 1;
+            }
+
+            if (input.IsMenuSelect(ControllingPlayer, out player))
+            {
+                menuEntries[selectedEntry].OnSelectEntry(player);
+            }
+
+            if (input.MouseGesture.HasFlag(MouseGestureType.LeftClick))
+            {
+
+                Point clickLocation = new Point((int)input.CurrentMousePosition.X, (int)input.CurrentMousePosition.Y);
+                // iterate the entries to see if any were tapped
+                for (int i = 0; i < menuEntries.Count; i++)
+                {
+                    MenuEntry menuEntry = menuEntries[i];
+
+                    if (GetMenuEntryHitBounds(menuEntry).Contains(clickLocation))
+                    {
+                        // select the entry. since gestures are only available on Windows Phone,
+                        // we can safely pass PlayerIndex.One to all entries since there is only
+                        // one player on Windows Phone.
+                        OnSelectEntry(i, PlayerIndex.One);
+                    }
+                }
+            }
+
+            if (input.MouseGesture.HasFlag(MouseGestureType.Move))
+            {
+
+                Point clickLocation = new Point((int)input.CurrentMousePosition.X, (int)input.CurrentMousePosition.Y);
+                // iterate the entries to see if any were tapped
+                for (int i = 0; i < menuEntries.Count; i++)
+                {
+                    MenuEntry menuEntry = menuEntries[i];
+
+                    if (GetMenuEntryHitBounds(menuEntry).Contains(clickLocation))
+                    {
+                        // select the entry. since gestures are only available on Windows Phone,
+                        // we can safely pass PlayerIndex.One to all entries since there is only
+                        // one player on Windows Phone.
+                        //OnSelectEntry(i, PlayerIndex.One);
+                        selectedEntry = i;
+                    }
+                }
+            }
 
             // look for any taps that occurred and select any entries that were tapped
             foreach (GestureSample gesture in input.Gestures)
@@ -165,7 +159,6 @@ namespace CatapultGame
             }
         }
 
-
         /// <summary>
         /// Handler for when the user has chosen a menu entry.
         /// </summary>
@@ -174,7 +167,6 @@ namespace CatapultGame
             menuEntries[entryIndex].OnSelectEntry(playerIndex);
         }
 
-
         /// <summary>
         /// Handler for when the user has cancelled the menu.
         /// </summary>
@@ -183,7 +175,6 @@ namespace CatapultGame
             ExitScreen();
         }
 
-
         /// <summary>
         /// Helper overload makes it easy to use OnCancel as a MenuEntry event handler.
         /// </summary>
@@ -192,10 +183,6 @@ namespace CatapultGame
             OnCancel(e.PlayerIndex);
         }
 
-
-
-
-
         /// <summary>
         /// Allows the screen the chance to position the menu entries. By default
         /// all menu entries are lined up in a vertical list, centered on the screen.
@@ -214,7 +201,7 @@ namespace CatapultGame
             for (int i = 0; i < menuEntries.Count; i++)
             {
                 MenuEntry menuEntry = menuEntries[i];
-                
+
                 // each entry is to be centered horizontally
                 position.X = ScreenManager.GraphicsDevice.Viewport.Width / 2 - menuEntry.GetWidth(this) / 2;
 
@@ -243,24 +230,24 @@ namespace CatapultGame
             for (int i = 0; i < menuEntries.Count; i++)
             {
                 bool isSelected = IsActive && (i == selectedEntry);
-//				if (!menuEntries[i].HasMouseEnteredAttached)
-//					menuEntries [i].MouseEntered += MouseEntered;
-//				if (!menuEntries[i].HasMouseClickedAttached)
-//					menuEntries [i].MouseClicked += MouseClicked;
+                //				if (!menuEntries[i].HasMouseEnteredAttached)
+                //					menuEntries [i].MouseEntered += MouseEntered;
+                //				if (!menuEntries[i].HasMouseClickedAttached)
+                //					menuEntries [i].MouseClicked += MouseClicked;
                 menuEntries[i].Update(this, isSelected, gameTime);
             }
         }
 
-//		void MouseClicked (object sender, MenuEntryEventArgs e)
-//		{
-//			e.MenuEntry.OnSelectEntry(PlayerIndex.One);
-//		}
-//
-//		void MouseEntered (object sender, MenuEntryEventArgs e)
-//		{
-//			//Console.WriteLine("Mouse Entered menu item " + e.MenuEntry.Text);
-//			selectedEntry = menuEntries.IndexOf(e.MenuEntry);
-//		}
+        //		void MouseClicked (object sender, MenuEntryEventArgs e)
+        //		{
+        //			e.MenuEntry.OnSelectEntry(PlayerIndex.One);
+        //		}
+        //
+        //		void MouseEntered (object sender, MenuEntryEventArgs e)
+        //		{
+        //			//Console.WriteLine("Mouse Entered menu item " + e.MenuEntry.Text);
+        //			selectedEntry = menuEntries.IndexOf(e.MenuEntry);
+        //		}
 
         /// <summary>
         /// Draws the menu.
@@ -274,7 +261,7 @@ namespace CatapultGame
             SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
             SpriteFont font = ScreenManager.Font;
 
-            spriteBatch.Begin();
+            spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, ScreenManager.GlobalTransformation);
 
             // Draw each menu entry in turn.
             for (int i = 0; i < menuEntries.Count; i++)
@@ -304,7 +291,5 @@ namespace CatapultGame
 
             spriteBatch.End();
         }
-
-
     }
-}
+}

+ 82 - 30
CatapultNetWars/Core/ScreenManager/ScreenManager.cs

@@ -25,11 +25,11 @@ namespace CatapultGame
     /// </summary>
     public class ScreenManager : DrawableGameComponent
     {
-
         List<GameScreen> screens = new List<GameScreen>();
         List<GameScreen> screensToUpdate = new List<GameScreen>();
 
-        InputState input = new InputState();
+        InputState inputState = new InputState(BASE_BUFFER_WIDTH, BASE_BUFFER_HEIGHT);
+        public InputState InputState => inputState;
 
         SpriteBatch spriteBatch;
         SpriteFont font;
@@ -39,8 +39,24 @@ namespace CatapultGame
 
         bool traceEnabled;
 
+        internal const int BASE_BUFFER_WIDTH = 800;
+        internal const int BASE_BUFFER_HEIGHT = 480;
+
+        private int backbufferWidth;
+        /// <summary>Gets or sets the current backbuffer width.</summary>
+        public int BackbufferWidth { get => backbufferWidth; set => backbufferWidth = value; }
+
+        private int backbufferHeight;
+        /// <summary>Gets or sets the current backbuffer height.</summary>
+        public int BackbufferHeight { get => backbufferHeight; set => backbufferHeight = value; }
 
+        private Vector2 baseScreenSize = new Vector2(BASE_BUFFER_WIDTH, BASE_BUFFER_HEIGHT);
+        /// <summary>Gets or sets the base screen size used for scaling calculations.</summary>
+        public Vector2 BaseScreenSize { get => baseScreenSize; set => baseScreenSize = value; }
 
+        private Matrix globalTransformation;
+        /// <summary>Gets or sets the global transformation matrix for scaling and positioning.</summary>
+        public Matrix GlobalTransformation { get => globalTransformation; set => globalTransformation = value; }
 
         /// <summary>
         /// A default SpriteBatch shared by all the screens. This saves
@@ -51,7 +67,6 @@ namespace CatapultGame
             get { return spriteBatch; }
         }
 
-
         /// <summary>
         /// A default font shared by all the screens. This saves
         /// each screen having to bother loading their own local copy.
@@ -61,7 +76,6 @@ namespace CatapultGame
             get { return font; }
         }
 
-
         /// <summary>
         /// If true, the manager prints out a list of all the screens
         /// each time it is updated. This can be useful for making sure
@@ -73,10 +87,6 @@ namespace CatapultGame
             set { traceEnabled = value; }
         }
 
-
-
-
-
         /// <summary>
         /// Constructs a new screen manager component.
         /// </summary>
@@ -88,7 +98,6 @@ namespace CatapultGame
             TouchPanel.EnabledGestures = GestureType.None;
         }
 
-
         /// <summary>
         /// Initializes the screen manager component.
         /// </summary>
@@ -99,7 +108,6 @@ namespace CatapultGame
             isInitialized = true;
         }
 
-
         /// <summary>
         /// Load your graphics content.
         /// </summary>
@@ -119,7 +127,6 @@ namespace CatapultGame
             }
         }
 
-
         /// <summary>
         /// Unload your graphics content.
         /// </summary>
@@ -132,17 +139,13 @@ namespace CatapultGame
             }
         }
 
-
-
-
-
         /// <summary>
         /// Allows each screen to run logic.
         /// </summary>
         public override void Update(GameTime gameTime)
         {
             // Read the keyboard and gamepad.
-            input.Update();
+            inputState.Update();
 
             // Make a copy of the master screen list, to avoid confusion if
             // the process of updating one screen adds or removes others.
@@ -172,7 +175,7 @@ namespace CatapultGame
                     // give it a chance to handle input.
                     if (!otherScreenHasFocus)
                     {
-                        screen.HandleInput(input);
+                        screen.HandleInput(inputState);
 
                         otherScreenHasFocus = true;
                     }
@@ -190,7 +193,6 @@ namespace CatapultGame
 
         }
 
-
         /// <summary>
         /// Prints a list of all the screens, for debugging.
         /// </summary>
@@ -204,7 +206,7 @@ namespace CatapultGame
             Console.WriteLine(string.Join(", ", screenNames.ToArray()));
         }
 
-		int count = 0;
+        int count = 0;
         /// <summary>
         /// Tells each screen to draw itself.
         /// </summary>
@@ -219,10 +221,6 @@ namespace CatapultGame
             }
         }
 
-
-
-
-
         /// <summary>
         /// Adds a new screen to the screen manager.
         /// </summary>
@@ -244,7 +242,6 @@ namespace CatapultGame
             TouchPanel.EnabledGestures = screen.EnabledGestures;
         }
 
-
         /// <summary>
         /// Removes a screen from the screen manager. You should normally
         /// use GameScreen.ExitScreen instead of calling this directly, so
@@ -270,7 +267,6 @@ namespace CatapultGame
             }
         }
 
-
         /// <summary>
         /// Expose an array holding all the screens. We return a copy rather
         /// than the real master list, because screens should only ever be added
@@ -281,7 +277,6 @@ namespace CatapultGame
             return screens.ToArray();
         }
 
-
         /// <summary>
         /// Helper draws a translucent black fullscreen sprite, used for fading
         /// screens in and out, and for darkening the background behind popups.
@@ -290,7 +285,7 @@ namespace CatapultGame
         {
             Viewport viewport = GraphicsDevice.Viewport;
 
-            spriteBatch.Begin();
+            spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, GlobalTransformation);
 
             spriteBatch.Draw(blankTexture,
                              new Rectangle(0, 0, viewport.Width, viewport.Height),
@@ -372,7 +367,7 @@ namespace CatapultGame
                         if (storage.FileExists("ScreenManager\\ScreenList.dat"))
                         {
                             // load the list of screen types
-                            using (IsolatedStorageFileStream stream = 
+                            using (IsolatedStorageFileStream stream =
                                 storage.OpenFile("ScreenManager\\ScreenList.dat", FileMode.Open, FileAccess.Read))
                             {
                                 using (BinaryReader reader = new BinaryReader(stream))
@@ -398,7 +393,7 @@ namespace CatapultGame
                         for (int i = 0; i < screens.Count; i++)
                         {
                             string filename = string.Format("ScreenManager\\Screen{0}.dat", i);
-                            using (IsolatedStorageFileStream stream = 
+                            using (IsolatedStorageFileStream stream =
                                 storage.OpenFile(filename, FileMode.Open, FileAccess.Read))
                             {
                                 screens[i].Deserialize(stream);
@@ -433,5 +428,62 @@ namespace CatapultGame
             }
         }
 
+        /// <summary>
+        /// Scales the game presentation area to match the screen's aspect ratio.
+        /// </summary>
+        public void ScalePresentationArea()
+        {
+            // Validate parameters before calculation
+            if (GraphicsDevice == null || baseScreenSize.X <= 0 || baseScreenSize.Y <= 0)
+            {
+                throw new InvalidOperationException("Invalid graphics configuration");
+            }
+
+            // Fetch screen dimensions
+            backbufferWidth = GraphicsDevice.PresentationParameters.BackBufferWidth;
+            backbufferHeight = GraphicsDevice.PresentationParameters.BackBufferHeight;
+
+            // Prevent division by zero
+            if (backbufferHeight == 0 || baseScreenSize.Y == 0)
+            {
+                return;
+            }
+
+            // Calculate aspect ratios
+            float baseAspectRatio = baseScreenSize.X / baseScreenSize.Y;
+            float screenAspectRatio = backbufferWidth / (float)backbufferHeight;
+
+            // Determine uniform scaling factor
+            float scalingFactor;
+            float horizontalOffset = 0;
+            float verticalOffset = 0;
+
+            if (screenAspectRatio > baseAspectRatio)
+            {
+                // Wider screen: scale by height
+                scalingFactor = backbufferHeight / baseScreenSize.Y;
+
+                // Centre things horizontally.
+                horizontalOffset = (backbufferWidth - baseScreenSize.X * scalingFactor) / 2;
+            }
+            else
+            {
+                // Taller screen: scale by width
+                scalingFactor = backbufferWidth / baseScreenSize.X;
+
+                // Centre things vertically.
+                verticalOffset = (backbufferHeight - baseScreenSize.Y * scalingFactor) / 2;
+            }
+
+            // Update the transformation matrix
+            globalTransformation = Matrix.CreateScale(scalingFactor) *
+                                   Matrix.CreateTranslation(horizontalOffset, verticalOffset, 0);
+
+            // Update the inputTransformation with the Inverted globalTransformation
+            inputState.UpdateInputTransformation(Matrix.Invert(globalTransformation));
+
+            // Debug info
+            Debug.WriteLine($"Screen Size - Width[{backbufferWidth}] Height[{backbufferHeight}] ScalingFactor[{scalingFactor}]");
+        }
     }
-}
+}

+ 1 - 1
CatapultNetWars/Core/Screens/BackgroundScreen.cs

@@ -46,7 +46,7 @@ namespace CatapultGame
         {
             SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
 
-            spriteBatch.Begin();
+            spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, ScreenManager.GlobalTransformation);
 
             // Draw Background
             spriteBatch.Draw(background, new Vector2(0, 0),

+ 1 - 1
CatapultNetWars/Core/Screens/GameplayScreen.cs

@@ -296,7 +296,7 @@ namespace CatapultGame
 		/// <param name="gameTime">The elapsed time since last Draw</param>
 		public override void Draw(GameTime gameTime)
 		{
-			ScreenManager.SpriteBatch.Begin();
+			ScreenManager.SpriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, ScreenManager.GlobalTransformation);
 
 			// Render all parts of the screen
 			DrawBackground();

+ 1 - 1
CatapultNetWars/Core/Screens/InstructionsScreen.cs

@@ -69,7 +69,7 @@ namespace CatapultGame
 		{
 			SpriteBatch spriteBatch = ScreenManager.SpriteBatch;
 
-			spriteBatch.Begin ();
+			spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, ScreenManager.GlobalTransformation);
 
 			// Draw Background
 			spriteBatch.Draw (background, new Vector2 (0, 0),

+ 1 - 1
CatapultNetWars/Core/Screens/LoadingScreen.cs

@@ -192,7 +192,7 @@ namespace CatapultGame
 				message += new string('.', dotCount);
 
 				// Draw the text.
-				spriteBatch.Begin();
+				spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, ScreenManager.GlobalTransformation);
 				spriteBatch.DrawString(font, message, textPosition, color);
 				spriteBatch.End();
 			}

+ 1 - 1
CatapultNetWars/Core/Screens/MessageBoxScreen.cs

@@ -137,7 +137,7 @@ namespace CatapultGame
             // Fade the popup alpha during transitions.
             Color color = Color.White * TransitionAlpha;
 
-            spriteBatch.Begin();
+            spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, ScreenManager.GlobalTransformation);
 
             // Draw the background rectangle.
             spriteBatch.Draw(gradientTexture, backgroundRectangle, color);