Explorar el Código

Refactor to centralise InputState and used it everywhere.

Dominique Louis hace 1 mes
padre
commit
1671b1c4ff

+ 6 - 6
CardsStarterKit/Core/Game/Blackjack/Game/BlackjackCardGame.cs

@@ -46,7 +46,7 @@ namespace Blackjack
             new Vector2(100 * BlackjackGame.WidthScale, 25 * BlackjackGame.HeightScale);
         static Vector2 ringOffset = new Vector2(0, 110);
 
-        Vector2 frameSize = BlackjackGame.IsMobile ? new Vector2(162, 162) : new Vector2(180, 180);
+        Vector2 frameSize = UIUtilty.IsMobile ? new Vector2(162, 162) : new Vector2(180, 180);
 
         public BlackjackGameState State { get; set; }
         ScreenManager screenManager;
@@ -93,7 +93,7 @@ namespace Blackjack
             base.LoadContent();
             // Initialize a new bet component
             // You may need to pass input state from elsewhere
-            betGameComponent = new BetGameComponent(players, screenManager.input, Theme, this, screenManager.SpriteBatch, screenManager.GlobalTransformation);
+            betGameComponent = new BetGameComponent(players, screenManager.InputState, Theme, this, screenManager.SpriteBatch, screenManager.GlobalTransformation);
             Game.Components.Add(betGameComponent);
 
             // Initialize the game buttons
@@ -101,7 +101,7 @@ namespace Blackjack
             for (int buttonIndex = 0; buttonIndex < buttonsText.Length; buttonIndex++)
             {
                 Button button = new Button("ButtonRegular", "ButtonPressed",
-                    screenManager.input, this, screenManager.SpriteBatch, screenManager.GlobalTransformation)
+                    screenManager.InputState, this, screenManager.SpriteBatch, screenManager.GlobalTransformation)
                 {
                     Text = buttonsText[buttonIndex],
                     Bounds = new Rectangle(screenManager.SafeArea.Left + 10 + buttonIndex * 110,
@@ -116,7 +116,7 @@ namespace Blackjack
             }
 
             newGame = new Button("ButtonRegular", "ButtonPressed",
-                    screenManager.input, this, screenManager.SpriteBatch, screenManager.GlobalTransformation)
+                    screenManager.InputState, this, screenManager.SpriteBatch, screenManager.GlobalTransformation)
             {
                 Text = "New Hand",
 
@@ -1089,7 +1089,7 @@ namespace Blackjack
             // Add a button to return to the main menu
             Vector2 center = new Vector2(widthCenter, heightCenter);
             Button backButton = new Button("ButtonRegular", "ButtonPressed",
-                screenManager.input, this, screenManager.SpriteBatch, screenManager.GlobalTransformation)
+                screenManager.InputState, this, screenManager.SpriteBatch, screenManager.GlobalTransformation)
             {
                 Bounds = new Rectangle((int)center.X - 100, (int)center.Y + 80, 200, 50),
                 Font = this.Font,
@@ -1158,7 +1158,7 @@ namespace Blackjack
                             (Game.Components[componentIndex] as AnimatedCardsGameComponent);
                         animatedCard.AddAnimation(
                             new TransitionGameComponentAnimation(animatedCard.CurrentPosition,
-                            new Vector2(animatedCard.CurrentPosition.X, ScreenManager.BACK_BUFFER_HEIGHT))
+                            new Vector2(animatedCard.CurrentPosition.X, ScreenManager.BASE_BUFFER_HEIGHT))
                             {
                                 Duration = TimeSpan.FromSeconds(0.40),
                                 PerformWhenDone = RemoveComponent,

+ 12 - 13
CardsStarterKit/Core/Game/Blackjack/Misc/BetGameComponent.cs

@@ -96,7 +96,7 @@ namespace Blackjack
             // Calculate chips position for the chip buttons which allow placing the bet
             Rectangle size = chipsAssets[assetNames[0]].Bounds;
 
-            Rectangle bounds = new Rectangle(0, 0, ScreenManager.BACK_BUFFER_WIDTH, ScreenManager.BACK_BUFFER_HEIGHT);
+            Rectangle bounds = new Rectangle(0, 0, ScreenManager.BASE_BUFFER_WIDTH, ScreenManager.BASE_BUFFER_HEIGHT);
 
             positions[chipsAssets.Count - 1] = new Vector2(bounds.Left + 10,
                 bounds.Bottom - size.Height - 80);
@@ -186,7 +186,7 @@ namespace Blackjack
                         // for input on the chip buttons
                         ShowAndEnableButtons(true);
 
-                        HandleInput(Mouse.GetState());
+                        HandleInput();
                     }
                 }
 
@@ -229,27 +229,26 @@ namespace Blackjack
         /// Handle the input of adding chip on all platform
         /// </summary>
         /// <param name="mouseState">Mouse input information.</param>
-        private void HandleInput(MouseState mouseState)
+        private void HandleInput()
         {
             bool isPressed = false;
             Vector2 position = Vector2.Zero;
 
-            if (mouseState.LeftButton == ButtonState.Pressed)
+            // Check for tap gestures
+            if (input.Gestures.Count > 0 && input.Gestures[0].GestureType == GestureType.Tap)
             {
                 isPressed = true;
-                position = new Vector2(mouseState.X, mouseState.Y);
-            }
-            else if (inputHelper.IsPressed)
-            {
-                isPressed = true;
-                position = inputHelper.PointPosition;
+                position = input.Gestures[0].Position;
             }
-            else if ((input.Gestures.Count > 0) && input.Gestures[0].GestureType == GestureType.Tap)
+
+            // Check for mouse input
+            if (input.CurrentMouseState.LeftButton == ButtonState.Pressed)
             {
                 isPressed = true;
-                position = input.Gestures[0].Position;
+                position = new Vector2(input.CurrentMouseState.X, input.CurrentMouseState.Y);
             }
 
+            // Handle chip interaction logic
             if (isPressed)
             {
                 if (!isKeyDown)
@@ -547,7 +546,7 @@ namespace Blackjack
 
             // Add transition animation
             chipComponent.AddAnimation(new TransitionGameComponentAnimation(positions[0],
-                new Vector2(ScreenManager.BACK_BUFFER_WIDTH / 2, insuranceYPosition))
+                new Vector2(ScreenManager.BASE_BUFFER_WIDTH / 2, insuranceYPosition))
             {
                 PerformBeforeStart = ShowComponent,
                 PerformBeforSartArgs = chipComponent,

+ 22 - 38
CardsStarterKit/Core/Game/Blackjack/UI/Button.cs

@@ -112,7 +112,7 @@ namespace Blackjack
         {
             if (RegularTexture != null)
             {
-                HandleInput(Mouse.GetState());
+                HandleInput();
             }
 
             base.Update(gameTime);
@@ -123,66 +123,50 @@ namespace Blackjack
         /// </summary>
         /// <param name="mouseState">Mouse input information.</param>
         /// <param name="inputHelper">Input of Xbox simulated cursor.</param>
-        private void HandleInput(MouseState mouseState)
+        private void HandleInput()
         {
             bool pressed = false;
             Vector2 position = Vector2.Zero;
 
-            if ((input.Gestures.Count > 0) && input.Gestures[0].GestureType == GestureType.Tap)
+            // Check for tap gestures
+            if (input.Gestures.Count > 0 && input.Gestures[0].GestureType == GestureType.Tap)
             {
                 pressed = true;
                 position = input.Gestures[0].Position;
             }
-            if (mouseState.LeftButton == ButtonState.Pressed)
-            {
-                pressed = true;
-                position = new Vector2(mouseState.X, mouseState.Y);
-            }
-            else if (inputHelper.IsPressed)
+
+            // Check for mouse input
+            if (input.CurrentMouseState.LeftButton == ButtonState.Pressed)
             {
                 pressed = true;
-                position = inputHelper.PointPosition;
+                position = new Vector2(input.CurrentMouseState.X, input.CurrentMouseState.Y);
             }
-            else
+
+            // Handle button press logic
+            if (pressed)
             {
-                if (isPressed)
+                if (!isKeyDown && IntersectWith(position))
                 {
-                    if (IntersectWith(new Vector2(mouseState.X, mouseState.Y)) ||
-                        IntersectWith(inputHelper.PointPosition))
+                    isPressed = true;
+
+                    if (UIUtilty.IsMobile)
                     {
                         FireClick();
                         isPressed = false;
                     }
-                    else
-                    {
-
-                        isPressed = false;
-                    }
-                }
 
-                isKeyDown = false;
-            }
-
-            if (pressed)
-            {
-                if (!isKeyDown)
-                {
-                    if (IntersectWith(position))
-                    {
-                        isPressed = true;
-
-                        if (BlackjackGame.IsMobile)
-                        {
-                            FireClick();
-                            isPressed = false;
-                        }
-
-                    }
                     isKeyDown = true;
                 }
             }
             else
             {
+                if (isPressed && (IntersectWith(new Vector2(input.CurrentMouseState.X, input.CurrentMouseState.Y)) ||
+                                  IntersectWith(inputHelper?.PointPosition ?? Vector2.Zero)))
+                {
+                    FireClick();
+                }
+
+                isPressed = false;
                 isKeyDown = false;
             }
         }

+ 4 - 14
CardsStarterKit/Core/Game/BlackjackGame.cs

@@ -31,16 +31,6 @@ namespace Blackjack
         public static float HeightScale = 1.0f;
         public static float WidthScale = 1.0f;
 
-        /// <summary>
-        /// Indicates if the game is running on a mobile platform.
-        /// </summary>
-        public readonly static bool IsMobile = OperatingSystem.IsAndroid() || OperatingSystem.IsIOS();
-
-        /// <summary>
-        /// Indicates if the game is running on a desktop platform.
-        /// </summary>
-        public readonly static bool IsDesktop = OperatingSystem.IsMacOS() || OperatingSystem.IsLinux() || OperatingSystem.IsWindows();
-
         /// <summary>
         /// Initializes a new instance of the game.
         /// </summary>
@@ -50,12 +40,12 @@ namespace Blackjack
 
             Content.RootDirectory = "Content";
 
-            if (IsMobile)
+            if (UIUtilty.IsMobile)
             {
                 graphicsDeviceManager.IsFullScreen = true;
                 IsMouseVisible = false;
             }
-            else if (IsDesktop)
+            else if (UIUtilty.IsDesktop)
             {
                 graphicsDeviceManager.IsFullScreen = false;
                 IsMouseVisible = true;
@@ -80,8 +70,8 @@ namespace Blackjack
         {
             base.Initialize();
 
-            graphicsDeviceManager.PreferredBackBufferWidth = ScreenManager.BACK_BUFFER_WIDTH;
-            graphicsDeviceManager.PreferredBackBufferHeight = ScreenManager.BACK_BUFFER_HEIGHT;
+            graphicsDeviceManager.PreferredBackBufferWidth = ScreenManager.BASE_BUFFER_WIDTH;
+            graphicsDeviceManager.PreferredBackBufferHeight = ScreenManager.BASE_BUFFER_HEIGHT;
             graphicsDeviceManager.ApplyChanges();
 
             float scale = screenManager.GlobalTransformation.M11; // uniform scale

+ 5 - 5
CardsStarterKit/Core/Game/Misc/InputHelper.cs

@@ -38,11 +38,11 @@ namespace Blackjack
             this.screenManager = screenManager;
             texture = screenManager.Game.Content.Load<Texture2D>(Path.Combine("Images", "GamePadCursor"));
             spriteBatch = screenManager.SpriteBatch;
-            maxVelocity = (float)(ScreenManager.BACK_BUFFER_WIDTH +
-                                  ScreenManager.BACK_BUFFER_HEIGHT) / 3000f;
+            maxVelocity = (float)(ScreenManager.BASE_BUFFER_WIDTH +
+                                  ScreenManager.BASE_BUFFER_HEIGHT) / 3000f;
 
-            drawPosition = new Vector2(ScreenManager.BACK_BUFFER_WIDTH / 2,
-                ScreenManager.BACK_BUFFER_HEIGHT / 2);
+            drawPosition = new Vector2(ScreenManager.BASE_BUFFER_WIDTH / 2,
+                ScreenManager.BASE_BUFFER_HEIGHT / 2);
         }
 
         //public static InputHelper Instance
@@ -81,7 +81,7 @@ namespace Blackjack
                 * gameTime.ElapsedGameTime.Milliseconds
                 * maxVelocity;
             drawPosition = Vector2.Clamp(drawPosition, Vector2.Zero,
-                new Vector2(ScreenManager.BACK_BUFFER_WIDTH, ScreenManager.BACK_BUFFER_HEIGHT)
+                new Vector2(ScreenManager.BASE_BUFFER_WIDTH, ScreenManager.BASE_BUFFER_HEIGHT)
                 - new Vector2(texture.Bounds.Width, texture.Bounds.Height));
         }
 

+ 1 - 18
CardsStarterKit/Core/Game/ScreenManager/GameScreen.cs

@@ -10,6 +10,7 @@ using Microsoft.Xna.Framework;
 using Microsoft.Xna.Framework.Input.Touch;
 using System.IO;
 using Microsoft.Xna.Framework.Graphics;
+using CardsFramework;
 
 namespace GameStateManagement
 {
@@ -34,8 +35,6 @@ namespace GameStateManagement
     /// </summary>
     public abstract class GameScreen
     {
-
-
         /// <summary>
         /// Normally when one screen is brought up over the top of another,
         /// the first screen will transition off to make room for the new
@@ -63,7 +62,6 @@ namespace GameStateManagement
 
         TimeSpan transitionOnTime = TimeSpan.Zero;
 
-
         /// <summary>
         /// Indicates how long the screen takes to
         /// transition off when it is deactivated.
@@ -76,7 +74,6 @@ namespace GameStateManagement
 
         TimeSpan transitionOffTime = TimeSpan.Zero;
 
-
         /// <summary>
         /// Gets the current position of the screen transition, ranging
         /// from zero (fully active, no transition) to one (transitioned
@@ -90,7 +87,6 @@ namespace GameStateManagement
 
         float transitionPosition = 1;
 
-
         /// <summary>
         /// Gets the current alpha of the screen transition, ranging
         /// from 1 (fully active, no transition) to 0 (transitioned
@@ -101,7 +97,6 @@ namespace GameStateManagement
             get { return 1f - TransitionPosition; }
         }
 
-
         /// <summary>
         /// Gets the current screen transition state.
         /// </summary>
@@ -113,7 +108,6 @@ namespace GameStateManagement
 
         ScreenState screenState = ScreenState.TransitionOn;
 
-
         /// <summary>
         /// There are two possible reasons why a screen might be transitioning
         /// off. It could be temporarily going away to make room for another
@@ -127,10 +121,8 @@ namespace GameStateManagement
             get { return isExiting; }
             protected internal set { isExiting = value; }
         }
-
         bool isExiting = false;
 
-
         /// <summary>
         /// Checks whether this screen is active and can respond to user input.
         /// </summary>
@@ -157,7 +149,6 @@ namespace GameStateManagement
 
         ScreenManager screenManager;
 
-
         /// <summary>
         /// 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
@@ -215,10 +206,6 @@ namespace GameStateManagement
 
         bool isSerializable = true;
 
-
-
-
-
         /// <summary>
         /// Load graphics content for the screen.
         /// </summary>
@@ -232,10 +219,6 @@ namespace GameStateManagement
         /// </summary>
         public virtual void UnloadContent() { }
 
-
-
-
-
         /// <summary>
         /// Allows the screen to run logic, such as updating the transition position.
         /// Unlike HandleInput, this method is called regardless of whether the screen

+ 3 - 2
CardsStarterKit/Core/Game/ScreenManager/MenuEntry.cs

@@ -9,6 +9,7 @@ using System;
 using Microsoft.Xna.Framework;
 using Microsoft.Xna.Framework.Graphics;
 using Blackjack;
+using CardsFramework;
 
 namespace GameStateManagement
 {
@@ -91,7 +92,7 @@ namespace GameStateManagement
         {
             // there is no such thing as a selected item on Windows Phone, so we always
             // force isSelected to be false
-            if (BlackjackGame.IsMobile)
+            if (UIUtilty.IsMobile)
             {
                 isSelected = false;
             }
@@ -116,7 +117,7 @@ namespace GameStateManagement
             Color textColor = isSelected ? Color.White : Color.Black;
             Color tintColor = isSelected ? Color.White : Color.Gray;
 
-            if (BlackjackGame.IsMobile)
+            if (UIUtilty.IsMobile)
             {
                 // there is no such thing as a selected item on Windows Phone, so we always
                 // force isSelected to be false

+ 16 - 40
CardsStarterKit/Core/Game/ScreenManager/MenuScreen.cs

@@ -12,6 +12,7 @@ using Microsoft.Xna.Framework.Graphics;
 using Microsoft.Xna.Framework.Input.Touch;
 using Microsoft.Xna.Framework.Input;
 using Blackjack;
+using CardsFramework;
 
 namespace GameStateManagement
 {
@@ -76,99 +77,79 @@ namespace GameStateManagement
         /// </summary>
         public override void HandleInput(InputState input)
         {
-            // we cancel the current menu screen if the user presses the back button
+            // Cancel the current menu screen if the user presses the back button
             PlayerIndex player;
             if (input.IsNewButtonPress(Buttons.Back, ControllingPlayer, out player))
             {
                 OnCancel(player);
             }
 
-            if (BlackjackGame.IsDesktop)
+            if (UIUtilty.IsDesktop)
             {
-                // Take care of Keyboard input
+                // Handle keyboard input
                 if (input.IsMenuUp(ControllingPlayer))
                 {
                     selectedEntry--;
-
                     if (selectedEntry < 0)
                         selectedEntry = menuEntries.Count - 1;
                 }
                 else if (input.IsMenuDown(ControllingPlayer))
                 {
                     selectedEntry++;
-
                     if (selectedEntry >= menuEntries.Count)
                         selectedEntry = 0;
                 }
                 else if (input.IsNewKeyPress(Keys.Enter, ControllingPlayer, out player) ||
-                    input.IsNewKeyPress(Keys.Space, ControllingPlayer, out player))
+                         input.IsNewKeyPress(Keys.Space, ControllingPlayer, out player))
                 {
                     OnSelectEntry(selectedEntry, player);
                 }
 
-
-                MouseState state = Mouse.GetState();
-                if (state.LeftButton == ButtonState.Released)
+                // Handle mouse input using InputState
+                if (input.CurrentMouseState.LeftButton == ButtonState.Released)
                 {
                     if (isMouseDown)
                     {
                         isMouseDown = false;
-                        // convert the position to a Point that we can test against a Rectangle
-                        Point clickLocation = new Point(state.X, state.Y);
+                        Point clickLocation = new Point(input.CurrentMouseState.X, input.CurrentMouseState.Y);
 
-                        // iterate the entries to see if any were tapped
                         for (int i = 0; i < menuEntries.Count; i++)
                         {
                             MenuEntry menuEntry = menuEntries[i];
-
                             if (menuEntry.Destination.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);
                             }
                         }
                     }
                 }
-                else if (state.LeftButton == ButtonState.Pressed)
+                else if (input.CurrentMouseState.LeftButton == ButtonState.Pressed)
                 {
                     isMouseDown = true;
+                    Point clickLocation = new Point(input.CurrentMouseState.X, input.CurrentMouseState.Y);
 
-                    // convert the position to a Point that we can test against a Rectangle
-                    Point clickLocation = new Point(state.X, state.Y);
-
-                    // iterate the entries to see if any were tapped
                     for (int i = 0; i < menuEntries.Count; i++)
                     {
                         MenuEntry menuEntry = menuEntries[i];
-
                         if (menuEntry.Destination.Contains(clickLocation))
                             selectedEntry = i;
                     }
                 }
             }
-            else if (BlackjackGame.IsMobile)
+            else if (UIUtilty.IsMobile)
             {
-                // look for any taps that occurred and select any entries that were tapped
+                // Handle touch input
                 foreach (GestureSample gesture in input.Gestures)
                 {
                     if (gesture.GestureType == GestureType.Tap)
                     {
-                        // convert the position to a Point that we can test against a Rectangle
                         Point tapLocation = new Point((int)gesture.Position.X, (int)gesture.Position.Y);
 
-                        // iterate the entries to see if any were tapped
                         for (int i = 0; i < menuEntries.Count; i++)
                         {
                             MenuEntry menuEntry = menuEntries[i];
-
                             if (menuEntry.Destination.Contains(tapLocation))
                             {
-                                // 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);
                             }
                         }
@@ -177,23 +158,23 @@ namespace GameStateManagement
             }
             else
             {
-                // Take care of Gamepad input
+                // Handle gamepad input
                 if (input.IsMenuUp(ControllingPlayer))
                 {
                     selectedEntry--;
-
                     if (selectedEntry < 0)
                         selectedEntry = menuEntries.Count - 1;
                 }
                 else if (input.IsMenuDown(ControllingPlayer))
                 {
                     selectedEntry++;
-
                     if (selectedEntry >= menuEntries.Count)
                         selectedEntry = 0;
                 }
                 else if (input.IsNewButtonPress(Buttons.A, ControllingPlayer, out player))
+                {
                     OnSelectEntry(selectedEntry, player);
+                }
             }
         }
 
@@ -233,8 +214,6 @@ namespace GameStateManagement
             base.LoadContent();
         }
 
-
-
         /// <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.
@@ -257,7 +236,7 @@ namespace GameStateManagement
                 MenuEntry menuEntry = menuEntries[i];
 
                 // each entry is to be centered horizontally
-                position.X = ScreenManager.BACK_BUFFER_WIDTH / 2 - menuEntry.GetWidth(this) / 2;
+                position.X = ScreenManager.BASE_BUFFER_WIDTH / 2 - menuEntry.GetWidth(this) / 2;
 
                 if (ScreenState == ScreenState.TransitionOn)
                     position.X -= transitionOffset * 256;
@@ -291,7 +270,6 @@ namespace GameStateManagement
             }
         }
 
-
         /// <summary>
         /// Draws the menu.
         /// </summary>
@@ -335,8 +313,6 @@ namespace GameStateManagement
             spriteBatch.End();
         }
 
-
-
         public void UpdateMenuEntryDestination()
         {
             Rectangle bounds = ScreenManager.SafeArea;

+ 12 - 9
CardsStarterKit/Core/Game/ScreenManager/ScreenManager.cs

@@ -14,6 +14,7 @@ using Microsoft.Xna.Framework.Graphics;
 using Microsoft.Xna.Framework.Input.Touch;
 using System.IO;
 using System.IO.IsolatedStorage;
+using CardsFramework;
 
 namespace GameStateManagement
 {
@@ -28,7 +29,9 @@ namespace GameStateManagement
         List<GameScreen> screens = new List<GameScreen>();
         List<GameScreen> screensToUpdate = new List<GameScreen>();
 
-        public InputState input = new InputState();
+        InputState inputState = new InputState(BASE_BUFFER_WIDTH, BASE_BUFFER_HEIGHT);
+
+        public InputState InputState => inputState;
 
         SpriteBatch spriteBatch;
         SpriteFont font;
@@ -39,8 +42,8 @@ namespace GameStateManagement
 
         bool traceEnabled;
 
-        internal const int BACK_BUFFER_WIDTH = 800;
-        internal const int BACK_BUFFER_HEIGHT = 480;
+        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>
@@ -50,7 +53,7 @@ namespace GameStateManagement
         /// <summary>Gets or sets the current backbuffer height.</summary>
         public int BackbufferHeight { get => backbufferHeight; set => backbufferHeight = value; }
 
-        private Vector2 baseScreenSize = new Vector2(BACK_BUFFER_WIDTH, BACK_BUFFER_HEIGHT);
+        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; }
 
@@ -97,7 +100,7 @@ namespace GameStateManagement
             set { traceEnabled = value; }
         }
 
-        Rectangle safeArea = new Rectangle(0, 0, BACK_BUFFER_WIDTH, BACK_BUFFER_HEIGHT);
+        Rectangle safeArea = new Rectangle(0, 0, BASE_BUFFER_WIDTH, BASE_BUFFER_HEIGHT);
         /// <summary>
         /// Returns the portion of the screen where drawing is safely allowed.
         /// </summary>
@@ -169,7 +172,7 @@ namespace GameStateManagement
         public override void Update(GameTime gameTime)
         {
             // Read the keyboard and gamepad.
-            input.Update();
+            inputState.Update(gameTime);
 
             // Make a copy of the master screen list, to avoid confusion if
             // the process of updating one screen adds or removes others.
@@ -199,7 +202,7 @@ namespace GameStateManagement
                     // give it a chance to handle input.
                     if (!otherScreenHasFocus)
                     {
-                        screen.HandleInput(input);
+                        screen.HandleInput(inputState);
 
                         otherScreenHasFocus = true;
                     }
@@ -308,7 +311,7 @@ namespace GameStateManagement
             spriteBatch.Begin(SpriteSortMode.Deferred, null, null, null, null, null, GlobalTransformation);
 
             spriteBatch.Draw(blankTexture,
-                             new Rectangle(0, 0, BACK_BUFFER_WIDTH, BACK_BUFFER_HEIGHT),
+                             new Rectangle(0, 0, BASE_BUFFER_WIDTH, BASE_BUFFER_HEIGHT),
                              Color.Black * alpha);
 
             spriteBatch.End();
@@ -366,7 +369,7 @@ namespace GameStateManagement
                                    Matrix.CreateTranslation(horizontalOffset, verticalOffset, 0);
 
             // Update the inputTransformation with the Inverted globalTransformation
-            // TODO inputState.UpdateInputTransformation(Matrix.Invert(globalTransformation));
+            inputState.UpdateInputTransformation(Matrix.Invert(globalTransformation));
 
             // Debug info
             Debug.WriteLine($"Screen Size - Width[{backbufferWidth}] Height[{backbufferHeight}] ScalingFactor[{scalingFactor}]");

+ 1 - 1
CardsStarterKit/Core/Game/Screens/BackgroundScreen.cs

@@ -35,7 +35,7 @@ namespace Blackjack
         public override void LoadContent()
         {
             background = ScreenManager.Game.Content.Load<Texture2D>(Path.Combine("Images", "titlescreen"));
-            safeArea = new Rectangle(0, 0, ScreenManager.BACK_BUFFER_WIDTH, ScreenManager.BACK_BUFFER_HEIGHT);
+            safeArea = new Rectangle(0, 0, ScreenManager.BASE_BUFFER_WIDTH, ScreenManager.BASE_BUFFER_HEIGHT);
             base.LoadContent();
         }
 

+ 9 - 8
CardsStarterKit/Core/Game/Screens/InstructionScreen.cs

@@ -15,6 +15,7 @@ using GameStateManagement;
 using Microsoft.Xna.Framework.Input;
 using Microsoft.Xna.Framework.Input.Touch;
 using System.IO;
+using CardsFramework;
 
 namespace Blackjack
 {
@@ -55,14 +56,14 @@ namespace Blackjack
         /// Exit the screen after a tap or click
         /// </summary>
         /// <param name="input"></param>
-        private void HandleInput(MouseState mouseState, GamePadState padState)
+        private void HandleInput()
         {
             if (!isExit)
             {
-                if (BlackjackGame.IsMobile)
+                if (UIUtilty.IsMobile)
                 {
-                    if (ScreenManager.input.Gestures.Count > 0 &&
-                        ScreenManager.input.Gestures[0].GestureType == GestureType.Tap)
+                    if (ScreenManager.InputState.Gestures.Count > 0 &&
+                        ScreenManager.InputState.Gestures[0].GestureType == GestureType.Tap)
                     {
                         isExit = true;
                     }
@@ -70,12 +71,12 @@ namespace Blackjack
                 else
                 {
                     PlayerIndex result;
-                    if (mouseState.LeftButton == ButtonState.Pressed)
+                    if (ScreenManager.InputState.CurrentMouseState.LeftButton == ButtonState.Pressed)
                     {
                         isExit = true;
                     }
-                    else if (ScreenManager.input.IsNewButtonPress(Buttons.A, null, out result) ||
-                        ScreenManager.input.IsNewButtonPress(Buttons.Start, null, out result))
+                    else if (ScreenManager.InputState.IsNewButtonPress(Buttons.A, null, out result) ||
+                             ScreenManager.InputState.IsNewButtonPress(Buttons.Start, null, out result))
                     {
                         isExit = true;
                     }
@@ -102,7 +103,7 @@ namespace Blackjack
                 isExited = true;
             }
 
-            HandleInput(Mouse.GetState(), GamePad.GetState(PlayerIndex.One));
+            HandleInput();
 
             base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
         }

+ 194 - 22
CardsStarterKit/Core/Game/ScreenManager/InputState.cs → CardsStarterKit/Framework/ScreenManager/InputState.cs

@@ -8,9 +8,10 @@
 using Microsoft.Xna.Framework;
 using Microsoft.Xna.Framework.Input;
 using Microsoft.Xna.Framework.Input.Touch;
+using System;
 using System.Collections.Generic;
 
-namespace GameStateManagement
+namespace CardsFramework
 {
     /// <summary>
     /// Helper for reading input from keyboard, gamepad, and touch input. This class 
@@ -21,47 +22,97 @@ namespace GameStateManagement
     public class InputState
     {
 
-        public const int MaxInputs = 4;
+        public const int MaxInputs = 4; // Maximum number of supported input devices (e.g., players)
 
-        public readonly KeyboardState[] CurrentKeyboardStates;
+        // Current Inputstates - Tracks the latest state of all input devices
         public readonly GamePadState[] CurrentGamePadStates;
+        public readonly KeyboardState[] CurrentKeyboardStates;
+        public MouseState CurrentMouseState;
+        private int touchCount; // Number of active touch inputs
+        public TouchCollection CurrentTouchState;
 
-        public readonly KeyboardState[] LastKeyboardStates;
+        // Last Inputstates - Stores the previous frame's input states for detecting changes
         public readonly GamePadState[] LastGamePadStates;
+        public readonly KeyboardState[] LastKeyboardStates;
+        public MouseState LastMouseState;
+        public TouchCollection LastTouchState;
+
+        public readonly List<GestureSample> Gestures = new List<GestureSample>(); // Stores touch gestures
 
         public readonly bool[] GamePadWasConnected;
 
-        public TouchCollection TouchState;
+        /// <summary>
+        /// Cursor move speed in pixels per second
+        /// </summary>
+        private const float cursorMoveSpeed = 250.0f;
 
-        public readonly List<GestureSample> Gestures = new List<GestureSample>();
+        private Vector2 currentCursorLocation;
+        /// <summary>
+        /// Current location of our Cursor
+        /// </summary>
+        public Vector2 CurrentCursorLocation => currentCursorLocation;
 
+        private Vector2 lastCursorLocation;
+        /// <summary>
+        /// Current location of our Cursor
+        /// </summary>
+        public Vector2 LastCursorLocation => lastCursorLocation;
 
+        private bool isMouseWheelScrolledDown;
+        /// <summary>
+        /// Has the user scrolled the mouse wheel down?
+        /// </summary>
+        public bool IsMouseWheelScrolledDown => isMouseWheelScrolledDown;
 
+        private bool isMouseWheelScrolledUp;
+        private Matrix inputTransformation; // Used to transform input coordinates between screen and game space
+        private float baseBufferWidth;
+        private float baseBufferHeight;
 
+        /// <summary>
+        /// Has the user scrolled the mouse wheel up?
+        /// </summary>
+        public bool IsMouseWheelScrolledUp => isMouseWheelScrolledUp;
 
         /// <summary>
         /// Constructs a new input state.
         /// </summary>
-        public InputState()
+        public InputState(float baseBufferWidth, float baseBufferHeight)
         {
+            this.baseBufferWidth = baseBufferWidth;
+            this.baseBufferHeight = baseBufferHeight;
+
+            // Initialize arrays for multiple controller/keyboard states
             CurrentKeyboardStates = new KeyboardState[MaxInputs];
             CurrentGamePadStates = new GamePadState[MaxInputs];
 
-            LastKeyboardStates = CurrentKeyboardStates;
-            LastGamePadStates = CurrentGamePadStates;
+            LastKeyboardStates = new KeyboardState[MaxInputs];
+            LastGamePadStates = new GamePadState[MaxInputs];
 
             GamePadWasConnected = new bool[MaxInputs];
-        }
-
-
-
 
+            // Configure platform-specific input options
+            if (UIUtilty.IsMobile)
+            {
+                TouchPanel.EnabledGestures = GestureType.Tap;
+            }
+            else if (UIUtilty.IsDesktop)
+            {
+                // No desktop-specific initialization needed
+            }
+            else
+            {
+                // For now, we'll throw an exception if we don't know the platform
+                throw new PlatformNotSupportedException();
+            }
+        }
 
         /// <summary>
         /// Reads the latest state of the keyboard and gamepad.
         /// </summary>
-        public void Update()
+        public void Update(GameTime gameTime)
         {
+            // Update keyboard and gamepad states for all players
             for (int i = 0; i < MaxInputs; i++)
             {
                 LastKeyboardStates[i] = CurrentKeyboardStates[i];
@@ -78,15 +129,124 @@ namespace GameStateManagement
                 }
             }
 
-            TouchState = TouchPanel.GetState();
+            // Update mouse state
+            LastMouseState = CurrentMouseState;
+            CurrentMouseState = Mouse.GetState();
 
+            // Update touch state
+            touchCount = 0;
+            LastTouchState = CurrentTouchState;
+            CurrentTouchState = TouchPanel.GetState();
+
+            // Process all available gestures
             Gestures.Clear();
             while (TouchPanel.IsGestureAvailable)
             {
                 Gestures.Add(TouchPanel.ReadGesture());
             }
+
+            // Process touch inputs
+            foreach (TouchLocation location in CurrentTouchState)
+            {
+                switch (location.State)
+                {
+                    case TouchLocationState.Pressed:
+                        touchCount++;
+                        lastCursorLocation = currentCursorLocation;
+                        // Transform touch position to game coordinates
+                        currentCursorLocation = TransformCursorLocation(location.Position);
+                        break;
+                    case TouchLocationState.Moved:
+                        break;
+                    case TouchLocationState.Released:
+                        break;
+                }
+            }
+
+            // Handle mouse clicks as touch equivalents
+            if (IsLeftMouseButtonClicked())
+            {
+                lastCursorLocation = currentCursorLocation;
+                // Transform mouse position to game coordinates
+                currentCursorLocation = TransformCursorLocation(new Vector2(CurrentMouseState.X, CurrentMouseState.Y));
+                touchCount = 1;
+            }
+
+            if (IsMiddleMouseButtonClicked())
+            {
+                touchCount = 2; // Treat middle mouse click as double touch
+            }
+
+            if (IsRightMoustButtonClicked())
+            {
+                touchCount = 3; // Treat right mouse click as triple touch
+            }
+
+            // Reset mouse wheel flags
+            isMouseWheelScrolledUp = false;
+            isMouseWheelScrolledDown = false;
+
+            // Detect mouse wheel scrolling
+            if (CurrentMouseState.ScrollWheelValue != LastMouseState.ScrollWheelValue)
+            {
+                int scrollWheelDelta = CurrentMouseState.ScrollWheelValue - LastMouseState.ScrollWheelValue;
+
+                // Handle the scroll wheel event based on the delta
+                if (scrollWheelDelta > 0)
+                {
+                    // Mouse wheel scrolled up
+                    isMouseWheelScrolledUp = true;
+                }
+                else if (scrollWheelDelta < 0)
+                {
+                    // Mouse wheel scrolled down
+                    isMouseWheelScrolledDown = true;
+                }
+            }
+
+            // Update the cursor location using gamepad and keyboard
+            float elapsedTime = (float)gameTime.ElapsedGameTime.TotalSeconds;
+
+            // Move cursor with 1st gamepad thumbstick
+            if (CurrentGamePadStates[0].IsConnected)
+            {
+                lastCursorLocation = currentCursorLocation;
+
+                currentCursorLocation.X += CurrentGamePadStates[0].ThumbSticks.Left.X * elapsedTime * cursorMoveSpeed;
+                currentCursorLocation.Y -= CurrentGamePadStates[0].ThumbSticks.Left.Y * elapsedTime * cursorMoveSpeed;
+            }
+
+            // Keep cursor within bounds
+            currentCursorLocation.X = MathHelper.Clamp(currentCursorLocation.X, 0f, baseBufferWidth);
+            currentCursorLocation.Y = MathHelper.Clamp(currentCursorLocation.Y, 0f, baseBufferHeight);
         }
 
+        /// <summary>
+        /// Checks if left mouse button was clicked (pressed and then released)
+        /// </summary>
+        /// <returns>True if left mouse button was clicked, false otherwise.</returns>
+        internal bool IsLeftMouseButtonClicked()
+        {
+            return CurrentMouseState.LeftButton == ButtonState.Released && LastMouseState.LeftButton == ButtonState.Pressed;
+        }
+
+        /// <summary>
+        /// Checks if middle mouse button was clicked (pressed and then released)
+        /// </summary>
+        /// <returns>True if middle mouse button was clicked, false otherwise.</returns>
+        internal bool IsMiddleMouseButtonClicked()
+        {
+            return CurrentMouseState.MiddleButton == ButtonState.Released && LastMouseState.MiddleButton == ButtonState.Pressed;
+        }
+
+        /// <summary>
+        /// Checks if right mouse button was clicked (pressed and then released)
+        /// </summary>
+        /// <returns>True if right mouse button was clicked, false otherwise.</returns>
+        internal bool IsRightMoustButtonClicked()
+        {
+            return CurrentMouseState.RightButton == ButtonState.Released && LastMouseState.RightButton == ButtonState.Pressed;
+        }
 
         /// <summary>
         /// Helper for checking if a key was newly pressed during this update. The
@@ -117,7 +277,6 @@ namespace GameStateManagement
             }
         }
 
-
         /// <summary>
         /// Helper for checking if a button was newly pressed during this update.
         /// The controllingPlayer parameter specifies which player to read input for.
@@ -147,7 +306,6 @@ namespace GameStateManagement
             }
         }
 
-
         /// <summary>
         /// Checks for a "menu select" input action.
         /// The controllingPlayer parameter specifies which player to read input for.
@@ -163,7 +321,6 @@ namespace GameStateManagement
                    IsNewButtonPress(Buttons.Start, controllingPlayer, out playerIndex);
         }
 
-
         /// <summary>
         /// Checks for a "menu cancel" input action.
         /// The controllingPlayer parameter specifies which player to read input for.
@@ -178,7 +335,6 @@ namespace GameStateManagement
                    IsNewButtonPress(Buttons.Back, controllingPlayer, out playerIndex);
         }
 
-
         /// <summary>
         /// Checks for a "menu up" input action.
         /// The controllingPlayer parameter specifies which player to read
@@ -194,7 +350,6 @@ namespace GameStateManagement
                    IsNewButtonPress(Buttons.LeftThumbstickLeft, controllingPlayer, out playerIndex);
         }
 
-
         /// <summary>
         /// Checks for a "menu down" input action.
         /// The controllingPlayer parameter specifies which player to read
@@ -210,7 +365,6 @@ namespace GameStateManagement
                    IsNewButtonPress(Buttons.LeftThumbstickRight, controllingPlayer, out playerIndex);
         }
 
-
         /// <summary>
         /// Checks for a "pause the game" input action.
         /// The controllingPlayer parameter specifies which player to read
@@ -225,6 +379,24 @@ namespace GameStateManagement
                    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;
+        }
 
+        /// <summary>
+        /// Transforms touch/mouse positions from screen space to game space.
+        /// </summary>
+        /// <param name="mousePosition">The screen-space position to transform.</param>
+        /// <returns>The transformed position in game space.</returns>
+        public Vector2 TransformCursorLocation(Vector2 mousePosition)
+        {
+            // Transform back to cursor location
+            return Vector2.Transform(mousePosition, inputTransformation);
+        }
     }
-}
+}

+ 1 - 0
CardsStarterKit/Framework/UI/AnimatedGameComponent.cs

@@ -54,6 +54,7 @@ namespace CardsFramework
         {
             if (sharedSpriteBatch == null)
                 throw new ArgumentNullException(nameof(sharedSpriteBatch), "AnimatedGameComponent requires a valid SpriteBatch.");
+                
             CardGame = cardGame;
             CurrentFrame = currentFrame;
             TextColor = Color.Black;

+ 12 - 2
CardsStarterKit/Framework/Utils/UIUtilty.cs

@@ -13,6 +13,16 @@ namespace CardsFramework
 {
     public static class UIUtilty
     {
+        /// <summary>
+        /// Indicates if the game is running on a mobile platform.
+        /// </summary>
+        public readonly static bool IsMobile = OperatingSystem.IsAndroid() || OperatingSystem.IsIOS();
+
+        /// <summary>
+        /// Indicates if the game is running on a desktop platform.
+        /// </summary>
+        public readonly static bool IsDesktop = OperatingSystem.IsMacOS() || OperatingSystem.IsLinux() || OperatingSystem.IsWindows();
+        
         /// <summary>
         /// Gets the name of a card asset.
         /// </summary>
@@ -21,9 +31,9 @@ namespace CardsFramework
         public static string GetCardAssetName(TraditionalCard card)
         {
             return string.Format("{0}{1}",
-                ((card.Value | CardValue.FirstJoker) == 
+                ((card.Value | CardValue.FirstJoker) ==
                     CardValue.FirstJoker ||
-                (card.Value | CardValue.SecondJoker) == 
+                (card.Value | CardValue.SecondJoker) ==
                 CardValue.SecondJoker) ?
                     "" : card.Type.ToString(), card.Value);
         }