|
@@ -8,9 +8,10 @@
|
|
using Microsoft.Xna.Framework;
|
|
using Microsoft.Xna.Framework;
|
|
using Microsoft.Xna.Framework.Input;
|
|
using Microsoft.Xna.Framework.Input;
|
|
using Microsoft.Xna.Framework.Input.Touch;
|
|
using Microsoft.Xna.Framework.Input.Touch;
|
|
|
|
+using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Generic;
|
|
|
|
|
|
-namespace GameStateManagement
|
|
|
|
|
|
+namespace CardsFramework
|
|
{
|
|
{
|
|
/// <summary>
|
|
/// <summary>
|
|
/// Helper for reading input from keyboard, gamepad, and touch input. This class
|
|
/// Helper for reading input from keyboard, gamepad, and touch input. This class
|
|
@@ -21,47 +22,97 @@ namespace GameStateManagement
|
|
public class InputState
|
|
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 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 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 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>
|
|
/// <summary>
|
|
/// Constructs a new input state.
|
|
/// Constructs a new input state.
|
|
/// </summary>
|
|
/// </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];
|
|
CurrentKeyboardStates = new KeyboardState[MaxInputs];
|
|
CurrentGamePadStates = new GamePadState[MaxInputs];
|
|
CurrentGamePadStates = new GamePadState[MaxInputs];
|
|
|
|
|
|
- LastKeyboardStates = CurrentKeyboardStates;
|
|
|
|
- LastGamePadStates = CurrentGamePadStates;
|
|
|
|
|
|
+ LastKeyboardStates = new KeyboardState[MaxInputs];
|
|
|
|
+ LastGamePadStates = new GamePadState[MaxInputs];
|
|
|
|
|
|
GamePadWasConnected = new bool[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>
|
|
/// <summary>
|
|
/// Reads the latest state of the keyboard and gamepad.
|
|
/// Reads the latest state of the keyboard and gamepad.
|
|
/// </summary>
|
|
/// </summary>
|
|
- public void Update()
|
|
|
|
|
|
+ public void Update(GameTime gameTime)
|
|
{
|
|
{
|
|
|
|
+ // Update keyboard and gamepad states for all players
|
|
for (int i = 0; i < MaxInputs; i++)
|
|
for (int i = 0; i < MaxInputs; i++)
|
|
{
|
|
{
|
|
LastKeyboardStates[i] = CurrentKeyboardStates[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();
|
|
Gestures.Clear();
|
|
while (TouchPanel.IsGestureAvailable)
|
|
while (TouchPanel.IsGestureAvailable)
|
|
{
|
|
{
|
|
Gestures.Add(TouchPanel.ReadGesture());
|
|
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>
|
|
/// <summary>
|
|
/// Helper for checking if a key was newly pressed during this update. The
|
|
/// Helper for checking if a key was newly pressed during this update. The
|
|
@@ -117,7 +277,6 @@ namespace GameStateManagement
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
/// Helper for checking if a button was newly pressed during this update.
|
|
/// Helper for checking if a button was newly pressed during this update.
|
|
/// The controllingPlayer parameter specifies which player to read input for.
|
|
/// The controllingPlayer parameter specifies which player to read input for.
|
|
@@ -147,7 +306,6 @@ namespace GameStateManagement
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
/// Checks for a "menu select" input action.
|
|
/// Checks for a "menu select" input action.
|
|
/// The controllingPlayer parameter specifies which player to read input for.
|
|
/// The controllingPlayer parameter specifies which player to read input for.
|
|
@@ -163,7 +321,6 @@ namespace GameStateManagement
|
|
IsNewButtonPress(Buttons.Start, controllingPlayer, out playerIndex);
|
|
IsNewButtonPress(Buttons.Start, controllingPlayer, out playerIndex);
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
/// Checks for a "menu cancel" input action.
|
|
/// Checks for a "menu cancel" input action.
|
|
/// The controllingPlayer parameter specifies which player to read input for.
|
|
/// The controllingPlayer parameter specifies which player to read input for.
|
|
@@ -178,7 +335,6 @@ namespace GameStateManagement
|
|
IsNewButtonPress(Buttons.Back, controllingPlayer, out playerIndex);
|
|
IsNewButtonPress(Buttons.Back, controllingPlayer, out playerIndex);
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
/// Checks for a "menu up" input action.
|
|
/// Checks for a "menu up" input action.
|
|
/// The controllingPlayer parameter specifies which player to read
|
|
/// The controllingPlayer parameter specifies which player to read
|
|
@@ -194,7 +350,6 @@ namespace GameStateManagement
|
|
IsNewButtonPress(Buttons.LeftThumbstickLeft, controllingPlayer, out playerIndex);
|
|
IsNewButtonPress(Buttons.LeftThumbstickLeft, controllingPlayer, out playerIndex);
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
/// Checks for a "menu down" input action.
|
|
/// Checks for a "menu down" input action.
|
|
/// The controllingPlayer parameter specifies which player to read
|
|
/// The controllingPlayer parameter specifies which player to read
|
|
@@ -210,7 +365,6 @@ namespace GameStateManagement
|
|
IsNewButtonPress(Buttons.LeftThumbstickRight, controllingPlayer, out playerIndex);
|
|
IsNewButtonPress(Buttons.LeftThumbstickRight, controllingPlayer, out playerIndex);
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
/// <summary>
|
|
/// <summary>
|
|
/// Checks for a "pause the game" input action.
|
|
/// Checks for a "pause the game" input action.
|
|
/// The controllingPlayer parameter specifies which player to read
|
|
/// The controllingPlayer parameter specifies which player to read
|
|
@@ -225,6 +379,24 @@ namespace GameStateManagement
|
|
IsNewButtonPress(Buttons.Start, 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;
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ /// <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);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
-}
|
|
|
|
|
|
+}
|