Skip to content

Commit

Permalink
Support mocking game input
Browse files Browse the repository at this point in the history
isadorasophia committed Jan 10, 2025
1 parent b8b1fe6 commit e48cdc6
Showing 5 changed files with 112 additions and 5 deletions.
2 changes: 1 addition & 1 deletion bang
Submodule bang updated 1 files
+6 −0 src/Bang/World.cs
3 changes: 3 additions & 0 deletions src/Murder.Editor/Architect.cs
Original file line number Diff line number Diff line change
@@ -163,7 +163,10 @@ public override void SetWindowSize(Point screenSize, bool remember)
private void QuitToEditor()
{
Microsoft.Xna.Framework.Media.MediaPlayer.Stop();

Resume();
Input.LockInput(false);

SoundPlayer.Stop(Murder.Core.Sounds.SoundLayer.Any, fadeOut: false);

GameLogger.Verify(_sceneLoader is not null);
73 changes: 69 additions & 4 deletions src/Murder/Core/Input/PlayerInput.cs
Original file line number Diff line number Diff line change
@@ -4,16 +4,21 @@
using Murder.Utilities;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Numerics;
using System.Text;

namespace Murder.Core.Input
{
public class PlayerInput
{
public int[] AllButtons => _buttons.Keys.ToArray();
public int[] AllAxis => _axis.Keys.ToArray();
private readonly Dictionary<int, VirtualButton> _buttons = new();
private readonly Dictionary<int, VirtualAxis> _axis = new();
// Debug only
public int[] AllButtons => [.. _buttons.Keys];

// Debug only
public int[] AllAxis => [.. _axis.Keys];

private readonly Dictionary<int, VirtualButton> _buttons = [];
private readonly Dictionary<int, VirtualAxis> _axis = [];

private KeyboardState _rawPreviousKeyboardState;
private KeyboardState _rawCurrentKeyboardState;
@@ -38,6 +43,11 @@ public class PlayerInput

public bool MouseConsumed = false;

/// <summary>
/// This will freeze any external input from the user.
/// </summary>
private bool _lockInput = false;

/// <summary>
/// Scrollwheel delta
/// </summary>
@@ -55,6 +65,39 @@ public int ScrollWheel
private readonly KeyboardState _emptyKeyboardState = new KeyboardState();
private readonly MouseState _emptyMouseState = new MouseState();

public void LockInput(bool @lock)
{
if (!@lock)
{
_lockInput = false;
return;
}

UpdateOnEmpty();
_lockInput = true;
}

public void MockInput(int button)
{
if (_buttons.TryGetValue(button, out VirtualButton? virtualButton))
{
virtualButton.Press();
}
}

public void MockInput(int axis, Vector2 value)
{
if (_axis.TryGetValue(axis, out VirtualAxis? virtualAxis))
{
virtualAxis.Press(value);
}
}

public void MockNoInput()
{
UpdateOnEmpty();
}

public VirtualButton GetOrCreateButton(int button)
{
if (!_buttons.ContainsKey(button) || _buttons[button] == null)
@@ -149,6 +192,11 @@ public void Register(int button, params MouseButtons[] buttons)

public void Update()
{
if (_lockInput)
{
return;
}

_previousKeyboardState = _currentKeyboardState;
if (!KeyboardConsumed)
{
@@ -201,6 +249,22 @@ public void Update()
Calculator.RoundToInt(mouseState.Y));
}

public void UpdateOnEmpty()
{
_currentKeyboardState = _emptyKeyboardState;

InputState inputState = new(_currentKeyboardState, gamePadState: new(), _emptyMouseState);
foreach (var button in _buttons)
{
button.Value.Update(inputState);
}

foreach (var axis in _axis)
{
axis.Value.Update(inputState);
}
}

public void Bind(int button, Action<InputState> action)
{
GetOrCreateButton(button).OnPress += action;
@@ -734,6 +798,7 @@ public void ListenToKeyboardInput(bool enable, int maxCharacters = 32)
}

public string GetKeyboardInput() => _userKeyboardInput.ToString();

public void SetKeyboardInput(string value)
{
_userKeyboardInput.Clear();
27 changes: 27 additions & 0 deletions src/Murder/Core/Input/VirtualAxis.cs
Original file line number Diff line number Diff line change
@@ -136,6 +136,33 @@ public void Update(InputState inputState)
Consumed = false;
}

public void Press(Vector2 value)
{
PreviousValue = Value;
IntPreviousValue = IntValue;

Down = true;
Consumed = false;

Value = value;
PressedValue = new Point(MathF.Sign(Value.X), MathF.Sign(Value.Y));
IntValue = new Point(Calculator.PolarSnapToInt(Value.X), Calculator.PolarSnapToInt(Value.Y));

if (PressedX)
{
_pressedXStart = Game.NowUnscaled;
_nextXTick = Game.NowUnscaled + _firstTickDelay;
_tickX = true;
}

if (PressedY)
{
_pressedYStart = Game.NowUnscaled;
_nextYTick = Game.NowUnscaled + _firstTickDelay;
_tickY = true;
}
}

internal string GetDescriptor()
{
return StringHelper.ToHumanList(GetActiveButtonDescriptions(), ",", "or");
12 changes: 12 additions & 0 deletions src/Murder/Core/Input/VirtualButton.cs
Original file line number Diff line number Diff line change
@@ -52,6 +52,18 @@ public void Update(InputState inputState)
}
}

/// <summary>
/// Force pressing the button.
/// </summary>
public void Press()
{
Previous = false;
Down = true;
Consumed = false;

LastPressed = Game.NowUnscaled;
}

public string GetDescriptor()
{
return StringHelper.ToHumanList(GetActiveDescriptors(), ",", "or");

0 comments on commit e48cdc6

Please sign in to comment.