Created
January 7, 2022 16:43
-
-
Save ZachIsAGardner/baf18ba66ce43e191b27282f44522405 to your computer and use it in GitHub Desktop.
MonoGame Input Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using Microsoft.Xna.Framework; | |
using Microsoft.Xna.Framework.Graphics; | |
using Microsoft.Xna.Framework.Audio; | |
namespace MyMonoGame | |
{ | |
/// <summary>The current state of any kind of axis (gamepad stick, gamepad trigger)</summary> | |
public class AxisState | |
{ | |
public string Name; | |
public float Value; | |
public AxisState() { } | |
public AxisState(string name, float value) | |
{ | |
Name = name; | |
Value = value; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using Microsoft.Xna.Framework; | |
using Microsoft.Xna.Framework.Graphics; | |
using Microsoft.Xna.Framework.Audio; | |
namespace MyMonoGame | |
{ | |
/// <summary>Represents a gamepad that is plugged in or connected via bluetooth</summary> | |
public class GamePad | |
{ | |
public string Name; | |
public PlayerIndex Index; | |
public List<InputState> InputStates = new List<InputState>(); | |
public List<AxisState> AxisStates = new List<AxisState>(); | |
public bool IsAvailable => !Input.Controllers.Any(c => c.GamePadIndex == Index); | |
public GamePad() { } | |
public GamePad(string name, PlayerIndex index) | |
{ | |
Name = name; | |
Index = index; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.Linq; | |
using Microsoft.Xna.Framework; | |
using Microsoft.Xna.Framework.Input; | |
using Newtonsoft.Json; | |
namespace MyMonoGame | |
{ | |
/// <summary>Wrapper for all basic input</summary> | |
public static class Input | |
{ | |
public static List<InputState> KeyStates = new List<InputState>(); | |
public static List<InputState> MouseStates = new List<InputState>(); | |
public static List<GamePad> GamePads = new List<GamePad>(); | |
public static List<VirtualController> Controllers = new List<VirtualController>() | |
{ | |
VirtualController.DefaultKeyboardAndController(), | |
VirtualController.DefaultSharedKeyboardTwo() | |
}; | |
/// <summary> | |
/// Amount scrolled this frame. | |
/// </summary> | |
public static float MouseScroll = 0; | |
private static float oldScroll = 0; | |
private static float newScroll = 0; | |
private static float backTime = 0; | |
private static float backThreshold = 0.4f; | |
private static float backOffset = 0.05f; | |
public static Vector2 MousePosition; | |
public static Vector2 ScreenMousePosition; | |
public static Vector2 WorldMousePosition; | |
public static Dictionary<string, string> PrettyGamePadNames = new Dictionary<string, string>() | |
{ | |
{ "GpActionDown", "Action Down" }, | |
{ "GpActionRight", "Action Right" }, | |
{ "GpActionUp", "Action Up" }, | |
{ "GpActionLeft", "Action Left" }, | |
{ "GpUp", "Up" }, | |
{ "GpDown", "Down" }, | |
{ "GpLeft", "Left" }, | |
{ "GpRight", "Right" }, | |
{ "GpLeftBumper", "Left Bumper" }, | |
{ "GpRightBumper", "Right Bumper" }, | |
{ "GpLeftTrigger", "Left Trigger" }, | |
{ "GpRightTrigger", "Right Trigger" }, | |
{ "GpMenu", "Start" }, | |
{ "GpMenuAlternative", "Select" }, | |
{ "GpLeftStickX", "Left Stick X" }, | |
{ "GpLeftStickY", "Left Stick Y" }, | |
{ "GpRightStickX", "Right Stick X" }, | |
{ "GpRightStickY", "Right Stick Y" }, | |
{ "GpLeftStickXPlus", "Left Stick X Right" }, | |
{ "GpLeftStickXMinus", "Left Stick X Left" }, | |
{ "GpRightStickXPlus", "Right Stick X Right" }, | |
{ "GpRightStickXMinus", "Right Stick X Left" }, | |
{ "GpLeftStickYPlus", "Left Stick Y Up" }, | |
{ "GpLeftStickYMinus", "Left Stick Y Down" }, | |
{ "GpRightStickYPlus", "Right Stick Y Up" }, | |
{ "GpRightStickYMinus", "Right Stick Y Down" }, | |
}; | |
public static string PrettyName(string name) | |
{ | |
if (String.IsNullOrWhiteSpace(name)) return ""; | |
Input.PrettyGamePadNames.TryGetValue(name, out string prettyName); | |
return String.IsNullOrWhiteSpace(prettyName) ? name : prettyName; | |
} | |
public static bool IsPressed(string name, PlayerIndex? index = null) | |
{ | |
if (MyGame.PlayerCount == 1 || index == null) | |
{ | |
return KeyStates.Any(i => i.Name == name && i.State == InputStateType.Pressed) | |
|| MouseStates.Any(i => i.Name == name && i.State == InputStateType.Pressed) | |
|| GamePads.Any(g => g.InputStates.Any(i => i.Name == name && i.State == InputStateType.Pressed)); | |
} | |
else | |
{ | |
PlayerProfile profile = MyGame.PlayerProfiles.Find(p => p.Controller.GamePadIndex == index); | |
if (profile.Controller.GamePadIndex.HasValue) | |
{ | |
GamePad gamePad = GamePads.Find(g => g.Index == index); | |
return gamePad.InputStates.Any(i => i.Name == name && i.State == InputStateType.Pressed); | |
} | |
else | |
{ | |
return KeyStates.Any(i => i.Name == name && i.State == InputStateType.Pressed); | |
} | |
} | |
} | |
public static bool IsHeld(string name, PlayerIndex? index = null) | |
{ | |
if (MyGame.PlayerCount == 1 || index == null) | |
{ | |
return KeyStates.Any(i => i.Name == name && i.State == InputStateType.Held) | |
|| MouseStates.Any(i => i.Name == name && i.State == InputStateType.Held) | |
|| GamePads.Any(g => g.InputStates.Any(i => i.Name == name && i.State == InputStateType.Held)); | |
} | |
else | |
{ | |
PlayerProfile profile = MyGame.PlayerProfiles.Find(p => p.Controller.GamePadIndex == index); | |
if (profile.Controller.GamePadIndex.HasValue) | |
{ | |
GamePad gamePad = GamePads.Find(g => g.Index == index); | |
return gamePad.InputStates.Any(i => i.Name == name && i.State == InputStateType.Held); | |
} | |
else | |
{ | |
return KeyStates.Any(i => i.Name == name && i.State == InputStateType.Held); | |
} | |
} | |
} | |
public static bool IsPressedOrHeld(string name, PlayerIndex? index = null) | |
{ | |
bool result = false; | |
result = IsPressed(name, index) || IsHeld(name, index); | |
return result; | |
} | |
public static bool IsReleased(string name, PlayerIndex? index = null) | |
{ | |
if (MyGame.PlayerCount == 1 || index == null) | |
{ | |
return KeyStates.Any(i => i.Name == name && i.State == InputStateType.Released) | |
|| MouseStates.Any(i => i.Name == name && i.State == InputStateType.Released) | |
|| GamePads.Any(g => g.InputStates.Any(i => i.Name == name && i.State == InputStateType.Released)); | |
} | |
else | |
{ | |
PlayerProfile profile = MyGame.PlayerProfiles.Find(p => p.Controller.GamePadIndex == index); | |
if (profile.Controller.GamePadIndex.HasValue) | |
{ | |
GamePad gamePad = GamePads.Find(g => g.Index == index); | |
return gamePad.InputStates.Any(i => i.Name == name && i.State == InputStateType.Released); | |
} | |
else | |
{ | |
return KeyStates.Any(i => i.Name == name && i.State == InputStateType.Released); | |
} | |
} | |
} | |
public static float GetAxis(string name, PlayerIndex? index = null) | |
{ | |
// Check the gamepad with the provided index only | |
if (index != null) | |
{ | |
GamePad pad = GamePads.Find(g => g.Index == index); | |
if (pad != null) | |
{ | |
AxisState axisState = pad.AxisStates.Find(a => a.Name == name); | |
if (axisState != null) | |
{ | |
return axisState.Value; | |
} | |
} | |
} | |
// Just check all of the gamepads | |
else | |
{ | |
GamePad pad = GamePads.Find(g => | |
{ | |
AxisState axisState = g.AxisStates.Find(a => a.Name == name); | |
if (axisState != null && MathF.Abs(axisState.Value) > 0) | |
{ | |
return true; | |
} | |
else | |
{ | |
return false; | |
} | |
}); | |
if (pad != null) | |
return pad.AxisStates.Find(a => a.Name == name).Value; | |
} | |
return 0; | |
} | |
public static string ApplyKeyboardToString(string content) | |
{ | |
// Get input | |
IEnumerable<string> letters = Input.KeyStates | |
.Where(k => k.State == InputStateType.Pressed) | |
.Select(k => k.Name); | |
string input = String.Join("", letters); | |
if (backTime >= backThreshold) | |
{ | |
backTime = backThreshold - backOffset; | |
input = "back"; | |
} | |
// Process input | |
if (!String.IsNullOrWhiteSpace(input)) | |
{ | |
// Top Numbers | |
if (input.Length == 2 && input[0] == 'D') | |
{ | |
content += input[1].ToString(); | |
} | |
// NumPad | |
else if (input.Contains("NumPad")) | |
{ | |
content += input[6].ToString(); | |
} | |
// - or _ | |
else if (input.Contains("OemMinus")) | |
{ | |
content += (Input.IsPressedOrHeld("LeftShift")) ? "_" : "-"; | |
} | |
// - | |
else if (input.Contains("Subtract")) | |
{ | |
content += "-"; | |
} | |
// Individual characters | |
else if (input.Count() == 1 && !Input.IsPressedOrHeld("LeftControl")) | |
{ | |
content += (Input.IsPressedOrHeld("LeftShift")) | |
? input.ToUpper() | |
: input.ToLower(); | |
} | |
// Space | |
else if (input.ToLower() == "space") | |
{ | |
content += " "; | |
} | |
// Backspace | |
else if (input.ToLower() == "back" && !String.IsNullOrEmpty(content)) | |
{ | |
int start = Math.Max(0, content.Count() - 1); | |
content = content.Remove(start, 1); | |
} | |
} | |
return content; | |
} | |
static bool didInit = false; | |
static void Start() | |
{ | |
VirtualController configControllerOne = Config.Instance.Controllers.ElementAtOrDefault(0) ?? VirtualController.DefaultKeyboardAndController(); | |
VirtualController configControllerTwo = Config.Instance.Controllers.ElementAtOrDefault(1) ?? VirtualController.DefaultSharedKeyboardTwo(); | |
Controllers = new List<VirtualController>() | |
{ | |
configControllerOne, | |
configControllerTwo | |
}; | |
MyGame.PlayerProfiles = new List<PlayerProfile>() | |
{ | |
new PlayerProfile(1, Input.Controllers[0]), | |
new PlayerProfile(2, Input.Controllers[1]) | |
}; | |
} | |
public static void Update() | |
{ | |
if (!didInit) | |
{ | |
Start(); | |
didInit = true; | |
} | |
UpdateKeyboard(); | |
UpdateMouse(); | |
UpdateGamePads(); | |
Input.Controllers.ForEach(c => c.Update()); | |
UpdateLoopKeys(); | |
} | |
private static void UpdateKeyboard() | |
{ | |
KeyboardState keyboardState = Keyboard.GetState(); | |
Keys[] currentKeys = keyboardState.GetPressedKeys(); | |
// Print whatever is being pressed. | |
// if (currentKeys.Length > 0) | |
// { | |
// string log = ""; | |
// int i = 0; | |
// foreach (Keys key in currentKeys) | |
// { | |
// if (i != 0) log += ", "; | |
// log += key; | |
// i++; | |
// } | |
// Debug.WriteLine($"({keyboardState.GetPressedKeyCount()}) {log}"); | |
// } | |
// Iterate over keys being pressed | |
// Deal with "pressed" and "held." | |
foreach (Keys key in currentKeys) | |
{ | |
if (keyboardState.IsKeyDown(key)) | |
{ | |
// New Input | |
if (!KeyStates.Any(i => i.Name == key.ToString())) | |
{ | |
KeyStates.Add(new InputState() | |
{ | |
Name = key.ToString(), | |
State = InputStateType.Pressed | |
}); | |
} | |
// Existing Input | |
else | |
{ | |
foreach (InputState existingKey in KeyStates.Where(i => i.Name == key.ToString())) | |
{ | |
existingKey.State = InputStateType.Held; | |
} | |
} | |
} | |
} | |
KeyStates = KeyStates.Where(i => i.State != InputStateType.Released).ToList(); | |
// Deal with "on released." | |
foreach (InputState input in KeyStates) | |
{ | |
// Current inputs aren't being pressed. | |
if (!currentKeys.Any(k => k.ToString() == input.Name)) | |
{ | |
input.State = InputStateType.Released; | |
} | |
} | |
} | |
private static void UpdateMouse() | |
{ | |
oldScroll = newScroll; | |
MouseState mouseState = Mouse.GetState(); | |
newScroll = mouseState.ScrollWheelValue; | |
MouseScroll = newScroll - oldScroll; | |
MousePosition = new Vector2(mouseState.X, mouseState.Y); | |
ScreenMousePosition = new Vector2( | |
(Input.MousePosition.X - MyGame.Gameport.X) / (float)(Camera.AbsoluteScreenMultiplier), | |
(Input.MousePosition.Y - MyGame.Gameport.Y) / (float)(Camera.AbsoluteScreenMultiplier) | |
); | |
WorldMousePosition = new Vector2( | |
(Input.MousePosition.X - Camera.Position.X - MyGame.Gameport.X) / Camera.RelativeScreenMultiplier, | |
(Input.MousePosition.Y - Camera.Position.Y - MyGame.Gameport.Y) / Camera.RelativeScreenMultiplier | |
); | |
List<(string Name, ButtonState State)> clicks = new List<(string Name, ButtonState State)>(); | |
clicks.Add(("LeftButton", mouseState.LeftButton)); | |
clicks.Add(("MiddleButton", mouseState.MiddleButton)); | |
clicks.Add(("RightButton", mouseState.RightButton)); | |
// Iterate over keys being pressed | |
// Deal with "pressed" and "held." | |
foreach (var click in clicks) | |
{ | |
if (click.State.HasFlag(ButtonState.Pressed)) | |
{ | |
// New Input | |
if (!MouseStates.Any(i => i.Name == click.Name)) | |
{ | |
MouseStates.Add(new InputState() | |
{ | |
Name = click.Name.ToString(), | |
State = InputStateType.Pressed | |
}); | |
} | |
// Existing Input | |
else | |
{ | |
foreach (InputState existingKey in MouseStates.Where(i => i.Name == click.Name)) | |
{ | |
existingKey.State = InputStateType.Held; | |
} | |
} | |
} | |
} | |
MouseStates = MouseStates.Where(i => i.State != InputStateType.Released).ToList(); | |
// Deal with "on released." | |
foreach (InputState input in MouseStates) | |
{ | |
var click = clicks.Find(c => c.Name == input.Name); | |
// Current inputs aren't being pressed. | |
if (!click.State.HasFlag(ButtonState.Pressed)) | |
{ | |
input.State = InputStateType.Released; | |
} | |
} | |
} | |
private static void UpdateGamePads() | |
{ | |
List<PlayerIndex> indexes = new List<PlayerIndex>() | |
{ | |
PlayerIndex.One, | |
PlayerIndex.Two, | |
PlayerIndex.Three, | |
PlayerIndex.Four | |
}; | |
foreach (PlayerIndex index in indexes) | |
{ | |
GamePadCapabilities capabilities = Microsoft.Xna.Framework.Input.GamePad.GetCapabilities(index); | |
GamePad pad = GamePads.Find(g => g.Index == index); | |
if (capabilities.IsConnected) | |
{ | |
if (pad == null) | |
{ | |
pad = new GamePad(capabilities.DisplayName, index); | |
GamePads.Add(pad); | |
Factory.UiToast($"New GamePad connected at Port {index}"); | |
if (MyGame.PlayerCount == 2) Menu.ChooseInputSourceMenu(); | |
} | |
pad.InputStates = pad.InputStates.Where(i => i.State != InputStateType.Released).ToList(); | |
GamePadState state = Microsoft.Xna.Framework.Input.GamePad.GetState(index); | |
// Axises | |
pad.AxisStates = new List<AxisState>() { }; | |
// Sticks | |
List<AxisState> sticks = new List<AxisState>() | |
{ | |
new AxisState("GpLeftStickX", state.ThumbSticks.Left.X), | |
new AxisState("GpLeftStickY", state.ThumbSticks.Left.Y), | |
new AxisState("GpRightStickX", state.ThumbSticks.Right.X), | |
new AxisState("GpRightStickY", state.ThumbSticks.Right.Y) | |
}; | |
pad.AxisStates.AddRange(sticks); | |
float axisActiveThreshold = 0.25f; | |
foreach (AxisState axisState in sticks) | |
{ | |
if (MathF.Abs(axisState.Value) >= axisActiveThreshold) | |
{ | |
string name = axisState.Name + ((axisState.Value < 0) ? "Minus" : "Plus"); | |
// New Input | |
if (!pad.InputStates.Any(i => i.Name == name)) | |
{ | |
pad.InputStates.Add(new InputState() | |
{ | |
Name = name, | |
State = InputStateType.Pressed | |
}); | |
} | |
// Existing Input | |
else | |
{ | |
foreach (InputState existingButton in pad.InputStates.Where(i => i.Name == name)) | |
{ | |
existingButton.State = InputStateType.Held; | |
} | |
} | |
} | |
} | |
// Deal with "on released." | |
foreach (InputState input in pad.InputStates) | |
{ | |
var stick = sticks.Find(s => { string name = s.Name + ((s.Value < 0) ? "Minus" : "Plus"); return name == input.Name; }); | |
// Current inputs aren't being pressed. | |
if (stick == null || MathF.Abs(stick.Value) < axisActiveThreshold) | |
{ | |
input.State = InputStateType.Released; | |
} | |
} | |
// Triggers | |
List<AxisState> triggers = new List<AxisState>() | |
{ | |
new AxisState("GpLeftTrigger", state.Triggers.Left), | |
new AxisState("GpRightTrigger", state.Triggers.Right), | |
}; | |
pad.AxisStates.AddRange(triggers); | |
foreach (AxisState axisState in triggers) | |
{ | |
if (axisState.Value >= axisActiveThreshold) | |
{ | |
// New Input | |
if (!pad.InputStates.Any(i => i.Name == axisState.Name)) | |
{ | |
pad.InputStates.Add(new InputState() | |
{ | |
Name = axisState.Name, | |
State = InputStateType.Pressed | |
}); | |
} | |
// Existing Input | |
else | |
{ | |
foreach (InputState existingButton in pad.InputStates.Where(i => i.Name == axisState.Name)) | |
{ | |
existingButton.State = InputStateType.Held; | |
} | |
} | |
} | |
} | |
// Deal with "on released." | |
foreach (InputState input in pad.InputStates) | |
{ | |
var trigger = triggers.Find(s => s.Name == input.Name); | |
// Current inputs aren't being pressed. | |
if (trigger != null && trigger.Value < axisActiveThreshold) | |
{ | |
input.State = InputStateType.Released; | |
} | |
} | |
// Buttons | |
List<(string Name, ButtonState State)> buttonStates = new List<(string Name, ButtonState State)>() | |
{ | |
("GpActionDown", state.Buttons.A), | |
("GpActionRight", state.Buttons.B), | |
("GpActionUp", state.Buttons.Y), | |
("GpActionLeft", state.Buttons.X), | |
("GpUp", state.DPad.Up), | |
("GpDown", state.DPad.Down), | |
("GpLeft", state.DPad.Left), | |
("GpRight", state.DPad.Right), | |
("GpLeftBumper", state.Buttons.LeftShoulder), | |
("GpRightBumper", state.Buttons.RightShoulder), | |
("GpMenu", state.Buttons.Start), | |
("GpMenuAlternative", state.Buttons.Back), | |
}; | |
foreach ((string Name, ButtonState State) buttonState in buttonStates) | |
{ | |
if (buttonState.State == ButtonState.Pressed) | |
{ | |
// New Input | |
if (!pad.InputStates.Any(i => i.Name == buttonState.Name)) | |
{ | |
pad.InputStates.Add(new InputState() | |
{ | |
Name = buttonState.Name, | |
State = InputStateType.Pressed | |
}); | |
} | |
// Existing Input | |
else | |
{ | |
foreach (InputState existingButton in pad.InputStates.Where(i => i.Name == buttonState.Name)) | |
{ | |
existingButton.State = InputStateType.Held; | |
} | |
} | |
} | |
} | |
// Deal with "on released." | |
foreach (InputState input in pad.InputStates) | |
{ | |
// Current inputs aren't being pressed. | |
var buttonState = buttonStates.Find(s => s.Name == input.Name); | |
if (!String.IsNullOrWhiteSpace(buttonState.Name) && buttonState.State == ButtonState.Released) | |
{ | |
input.State = InputStateType.Released; | |
} | |
} | |
} | |
else | |
{ | |
if (pad != null) | |
{ | |
Factory.UiToast($"GamePad at Port {index} disconnected"); | |
GamePads.Remove(pad); | |
if (MyGame.PlayerCount == 2) Menu.ChooseInputSourceMenu(); | |
} | |
} | |
} | |
} | |
private static void UpdateLoopKeys() | |
{ | |
// Get input | |
IEnumerable<string> releasedLetters = Input.KeyStates | |
.Where(k => k.State == InputStateType.Released) | |
.Select(k => k.Name); | |
string releasedInput = String.Join("", releasedLetters); | |
if (releasedInput.ToLower() == "back") backTime = 0; | |
// Get input | |
IEnumerable<string> heldLetters = Input.KeyStates | |
.Where(k => k.State == InputStateType.Held) | |
.Select(k => k.Name); | |
string heldInput = String.Join("", heldLetters); | |
if (heldInput.ToLower() == "back") backTime += Time.Delta; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using Microsoft.Xna.Framework; | |
using Microsoft.Xna.Framework.Graphics; | |
using Microsoft.Xna.Framework.Audio; | |
namespace MyMonoGame | |
{ | |
/// <summary>The current state of any kind of input (keyboard key, gamepad button, mouse click, etc.)</summary> | |
public class InputState | |
{ | |
public string Name; | |
public InputStateType State; | |
public InputState() { } | |
public InputState(string name, InputStateType state) | |
{ | |
Name = name; | |
State = state; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using Microsoft.Xna.Framework; | |
using Microsoft.Xna.Framework.Graphics; | |
using Microsoft.Xna.Framework.Audio; | |
namespace MyMonoGame | |
{ | |
/// <summary>The possible states of one input (keyboard key, gamepad button, mouse click, etc.)</summary> | |
public enum InputStateType | |
{ | |
Pressed, | |
Held, | |
Released | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using Microsoft.Xna.Framework; | |
using Microsoft.Xna.Framework.Graphics; | |
using Microsoft.Xna.Framework.Audio; | |
using Newtonsoft.Json; | |
namespace MyMonoGame | |
{ | |
/// <summary>An axis that exists on a VirtualController</summary> | |
public class VirtualAxis | |
{ | |
// Axes/ Inputs | |
public List<string> Axes; | |
public VirtualButton NegativeButton; | |
public VirtualButton PositiveButton; | |
[JsonIgnore] | |
public VirtualController Controller; | |
[JsonIgnore] | |
public PlayerIndex? GamePadIndex => Controller?.GamePadIndex; | |
// Methods | |
public VirtualAxis() { } | |
public VirtualAxis(string negativeName, string positiveName, VirtualController controller, List<string> axes, List<string> negativeInputs = null, List<string> positiveInputs = null) | |
{ | |
Axes = axes; | |
NegativeButton = new VirtualButton(negativeName, controller, negativeInputs); | |
PositiveButton = new VirtualButton(positiveName, controller, positiveInputs); | |
Controller = controller; | |
} | |
// lol | |
[JsonIgnore] | |
public float Value => | |
// Negative Button | |
(NegativeButton.IsPressedOrHeld) | |
? -1 | |
// Positive Button | |
: (PositiveButton.IsPressedOrHeld) | |
? 1 | |
// Axes | |
: (Axes.Any(a => Input.GetAxis(a, GamePadIndex) != 0)) | |
? Input.GetAxis(Axes.First(a => Input.GetAxis(a, GamePadIndex) != 0)) | |
: 0; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using Microsoft.Xna.Framework; | |
using Microsoft.Xna.Framework.Graphics; | |
using Microsoft.Xna.Framework.Audio; | |
namespace MyMonoGame | |
{ | |
/// <summary>Represents an input configuration scheme. Encapsulates input across devices (gamepad, keyboard, mouse)</summary> | |
public partial class VirtualController | |
{ | |
public string Display => (MyGame.PlayerCount == 2) | |
? $"{(GamePadIndex.HasValue ? $"GamePad (Port: {GamePadIndex.Value})" : "Keyboard")}" | |
: "Any"; | |
/// <summary>Only relevant for gamepad input</summary> | |
public PlayerIndex? GamePadIndex = null; | |
public GamePad GamePad => Input.GamePads.Find(g => g.Index == GamePadIndex); | |
// Inputs | |
// Buttons | |
public VirtualButton Jump; | |
public VirtualButton Spit; | |
public VirtualButton Leap; | |
// public VirtualButton Interact; | |
public VirtualButton Start; | |
// Axes | |
public VirtualAxis Horizontal; | |
public VirtualAxis Vertical; | |
// Info | |
public List<VirtualButton> AllButtons => Buttons | |
.Concat(Axes.Select(a => a.NegativeButton)) | |
.Concat(Axes.Select(a => a.PositiveButton)) | |
.ToList(); | |
public List<VirtualButton> Buttons => new List<VirtualButton>() | |
{ | |
Jump, | |
Spit, | |
Leap, | |
// Interact, | |
Start | |
}; | |
public List<VirtualAxis> Axes => new List<VirtualAxis>() | |
{ | |
Horizontal, | |
Vertical | |
}; | |
private bool didInit = false; | |
// Methods | |
public VirtualController() { } | |
// Cycle | |
void Init() | |
{ | |
foreach (VirtualButton button in AllButtons) | |
button.Controller = this; | |
foreach (VirtualAxis axis in Axes) | |
axis.Controller = this; | |
} | |
public void Update() | |
{ | |
if (!didInit) | |
{ | |
Init(); | |
didInit = true; | |
} | |
CheckGamePadConnected(); | |
} | |
public void SetInputs(VirtualController other) | |
{ | |
Jump = other.Jump; | |
other.Jump.Controller = this; | |
Spit = other.Spit; | |
other.Spit.Controller = this; | |
Leap = other.Leap; | |
other.Leap.Controller = this; | |
// Interact = other.Interact; | |
// other.Interact.Controller = this; | |
Start = other.Start; | |
other.Start.Controller = this; | |
Horizontal = other.Horizontal; | |
other.Horizontal.Controller = this; | |
other.Horizontal.NegativeButton.Controller = this; | |
other.Horizontal.PositiveButton.Controller = this; | |
Vertical = other.Vertical; | |
other.Vertical.Controller = this; | |
other.Vertical.NegativeButton.Controller = this; | |
other.Vertical.PositiveButton.Controller = this; | |
} | |
public void ConcatInputs(VirtualController other) | |
{ | |
GamePadIndex = other.GamePadIndex; | |
Jump.Inputs.AddRange(other.Jump.Inputs); | |
Spit.Inputs.AddRange(other.Spit.Inputs); | |
Leap.Inputs.AddRange(other.Leap.Inputs); | |
Start.Inputs.AddRange(other.Start.Inputs); | |
Horizontal.NegativeButton.Inputs.AddRange(other.Horizontal.NegativeButton.Inputs); | |
Horizontal.PositiveButton.Inputs.AddRange(other.Horizontal.PositiveButton.Inputs); | |
Vertical.NegativeButton.Inputs.AddRange(other.Vertical.NegativeButton.Inputs); | |
Vertical.PositiveButton.Inputs.AddRange(other.Vertical.PositiveButton.Inputs); | |
} | |
void CheckGamePadConnected() | |
{ | |
if (!GamePadIndex.HasValue) return; | |
if (!Input.GamePads.Any(g => g.Index == GamePadIndex)) | |
{ | |
GamePadIndex = null; | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using Microsoft.Xna.Framework; | |
using Microsoft.Xna.Framework.Graphics; | |
using Microsoft.Xna.Framework.Audio; | |
namespace MyMonoGame | |
{ | |
public partial class VirtualController | |
{ | |
public static void SetControllersToDefault() | |
{ | |
if (MyGame.PlayerCount == 2) | |
{ | |
if (!Input.Controllers[0].GamePadIndex.HasValue && !Input.Controllers[1].GamePadIndex.HasValue) | |
{ | |
Input.Controllers[0].SetInputs(VirtualController.DefaultSharedKeyboardOne()); | |
Input.Controllers[1].SetInputs(VirtualController.DefaultSharedKeyboardTwo()); | |
} | |
else | |
{ | |
if (Input.Controllers[0].GamePadIndex.HasValue) | |
{ | |
Input.Controllers[0].SetInputs(VirtualController.DefaultController()); | |
} | |
else | |
{ | |
Input.Controllers[0].SetInputs(VirtualController.DefaultKeyboard()); | |
} | |
if (Input.Controllers[1].GamePadIndex.HasValue) | |
{ | |
Input.Controllers[1].SetInputs(VirtualController.DefaultController()); | |
} | |
else | |
{ | |
Input.Controllers[1].SetInputs(VirtualController.DefaultKeyboard()); | |
} | |
} | |
} | |
else | |
{ | |
Input.Controllers[0].SetInputs(VirtualController.DefaultKeyboardAndController()); | |
} | |
} | |
public static VirtualController DefaultBlank() | |
{ | |
VirtualController controller = new VirtualController(); | |
// Buttons | |
controller.Jump = new VirtualButton("Jump", controller, | |
new List<string>() | |
{ | |
} | |
); | |
controller.Spit = new VirtualButton("Spit", controller, | |
new List<string>() | |
{ | |
} | |
); | |
controller.Leap = new VirtualButton("Leap", controller, | |
new List<string>() | |
{ | |
} | |
); | |
controller.Start = new VirtualButton("Start", controller, | |
new List<string>() | |
{ | |
} | |
); | |
// Axes | |
controller.Horizontal = new VirtualAxis("Left", "Right", controller, | |
new List<string>() { }, | |
new List<string>() { }, | |
new List<string>() { } | |
); | |
controller.Vertical = new VirtualAxis("Down", "Up", controller, | |
new List<string>() { }, | |
new List<string>() { }, | |
new List<string>() { } | |
); | |
return controller; | |
} | |
public static VirtualController DefaultController() | |
{ | |
VirtualController controller = DefaultBlank(); | |
// Buttons | |
controller.Jump = new VirtualButton("Jump", controller, | |
new List<string>() | |
{ | |
"GpActionDown" | |
} | |
); | |
controller.Spit = new VirtualButton("Spit", controller, | |
new List<string>() | |
{ | |
"GpActionLeft" | |
} | |
); | |
controller.Leap = new VirtualButton("Leap", controller, | |
new List<string>() | |
{ | |
"GpActionRight" | |
} | |
); | |
controller.Start = new VirtualButton("Start", controller, | |
new List<string>() | |
{ | |
"GpMenu" | |
} | |
); | |
// Axes | |
controller.Horizontal = new VirtualAxis("Left", "Right", controller, | |
new List<string>() { }, | |
new List<string>() { "GpLeft", "GpLeftStickXMinus" }, | |
new List<string>() { "GpRight", "GpLeftStickXPlus" } | |
); | |
controller.Vertical = new VirtualAxis("Down", "Up", controller, | |
new List<string>() { }, | |
new List<string>() { "GpDown", "GpLeftStickYMinus" }, | |
new List<string>() { "GpUp", "GpLeftStickYPlus" } | |
); | |
return controller; | |
} | |
public static VirtualController DefaultKeyboard() | |
{ | |
VirtualController controller = DefaultBlank(); | |
// Buttons | |
controller.Jump = new VirtualButton("Jump", controller, | |
new List<string>() | |
{ | |
"Z", "J", "Space" | |
} | |
); | |
controller.Spit = new VirtualButton("Spit", controller, | |
new List<string>() | |
{ | |
"X", "K" | |
} | |
); | |
controller.Leap = new VirtualButton("Leap", controller, | |
new List<string>() | |
{ | |
"C", "L" | |
} | |
); | |
controller.Start = new VirtualButton("Start", controller, | |
new List<string>() | |
{ | |
"P" | |
} | |
); | |
if (!CONSTANTS.IS_DEBUG) | |
{ | |
controller.Start.Inputs.Add("Escape"); | |
} | |
// Axes | |
controller.Horizontal = new VirtualAxis("Left", "Right", controller, | |
new List<string>() { }, | |
new List<string>() { "Left", "A" }, | |
new List<string>() { "Right", "D" } | |
); | |
controller.Vertical = new VirtualAxis("Down", "Up", controller, | |
new List<string>() { }, | |
new List<string>() { "Down", "S" }, | |
new List<string>() { "Up", "W" } | |
); | |
return controller; | |
} | |
public static VirtualController DefaultKeyboardAndController() | |
{ | |
VirtualController controller = DefaultBlank(); | |
controller.ConcatInputs(DefaultController()); | |
controller.ConcatInputs(DefaultKeyboard()); | |
return controller; | |
} | |
// Shared Keyboard | |
public static VirtualController DefaultSharedKeyboardOne() | |
{ | |
VirtualController controller = DefaultBlank(); | |
controller.ConcatInputs(DefaultController()); | |
// Buttons | |
controller.Jump = new VirtualButton("Jump", controller, | |
new List<string>() | |
{ | |
"J", "Space" | |
} | |
); | |
controller.Spit = new VirtualButton("Spit", controller, | |
new List<string>() | |
{ | |
"K" | |
} | |
); | |
controller.Leap = new VirtualButton("Leap", controller, | |
new List<string>() | |
{ | |
"L" | |
} | |
); | |
controller.Start = new VirtualButton("Start", controller, | |
new List<string>() | |
{ | |
"P" | |
} | |
); | |
if (!CONSTANTS.IS_DEBUG) | |
{ | |
controller.Start.Inputs.Add("Escape"); | |
} | |
// Axes | |
controller.Horizontal = new VirtualAxis("Left", "Right", controller, | |
new List<string>() { }, | |
new List<string>() { "A" }, | |
new List<string>() { "D" } | |
); | |
controller.Vertical = new VirtualAxis("Down", "Up", controller, | |
new List<string>() { }, | |
new List<string>() { "S" }, | |
new List<string>() { "W" } | |
); | |
return controller; | |
} | |
public static VirtualController DefaultSharedKeyboardTwo() | |
{ | |
VirtualController controller = DefaultBlank(); | |
controller.ConcatInputs(DefaultController()); | |
// Buttons | |
controller.Jump = new VirtualButton("Jump", controller, | |
new List<string>() | |
{ | |
"NumPad0" | |
} | |
); | |
controller.Spit = new VirtualButton("Spit", controller, | |
new List<string>() | |
{ | |
"Decimal" | |
} | |
); | |
controller.Leap = new VirtualButton("Leap", controller, | |
new List<string>() | |
{ | |
"Enter" | |
} | |
); | |
controller.Start = new VirtualButton("Start", controller, | |
new List<string>() | |
{ | |
"NumPad9" | |
} | |
); | |
// Axes | |
controller.Horizontal = new VirtualAxis("Left", "Right", controller, | |
new List<string>() { }, | |
new List<string>() { "Left" }, | |
new List<string>() { "Right" } | |
); | |
controller.Vertical = new VirtualAxis("Down", "Up", controller, | |
new List<string>() { }, | |
new List<string>() { "Down" }, | |
new List<string>() { "Up" } | |
); | |
return controller; | |
} | |
// Cramped Keyboard | |
public static VirtualController DefaultSharedKeyboardCrampedOne() | |
{ | |
VirtualController controller = DefaultBlank(); | |
controller.ConcatInputs(DefaultController()); | |
// Buttons | |
controller.Jump = new VirtualButton("Jump", controller, | |
new List<string>() | |
{ | |
"T" | |
} | |
); | |
controller.Spit = new VirtualButton("Spit", controller, | |
new List<string>() | |
{ | |
"Y" | |
} | |
); | |
controller.Leap = new VirtualButton("Leap", controller, | |
new List<string>() | |
{ | |
"U" | |
} | |
); | |
controller.Start = new VirtualButton("Start", controller, | |
new List<string>() | |
{ | |
"I", "P" | |
} | |
); | |
// Axes | |
controller.Horizontal = new VirtualAxis("Left", "Right", controller, | |
new List<string>() { }, | |
new List<string>() { "Q" }, | |
new List<string>() { "E" } | |
); | |
controller.Vertical = new VirtualAxis("Down", "Up", controller, | |
new List<string>() { }, | |
new List<string>() { "W" }, | |
new List<string>() { "D2", "D3" } | |
); | |
return controller; | |
} | |
public static VirtualController DefaultSharedKeyboardCrampedTwo() | |
{ | |
VirtualController controller = DefaultBlank(); | |
controller.ConcatInputs(DefaultController()); | |
// Buttons | |
controller.Jump = new VirtualButton("Jump", controller, | |
new List<string>() | |
{ | |
"M" | |
} | |
); | |
controller.Spit = new VirtualButton("Spit", controller, | |
new List<string>() | |
{ | |
"OemComma" | |
} | |
); | |
controller.Leap = new VirtualButton("Leap", controller, | |
new List<string>() | |
{ | |
"OemPeriod" | |
} | |
); | |
controller.Start = new VirtualButton("Start", controller, | |
new List<string>() | |
{ | |
"OemQuestion" | |
} | |
); | |
// Axes | |
controller.Horizontal = new VirtualAxis("Left", "Right", controller, | |
new List<string>() { }, | |
new List<string>() { "C" }, | |
new List<string>() { "B" } | |
); | |
controller.Vertical = new VirtualAxis("Down", "Up", controller, | |
new List<string>() { }, | |
new List<string>() { "V" }, | |
new List<string>() { "F", "G" } | |
); | |
return controller; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment