Merge pull request #35 from ClassicThunder/master

MonoGame-EventDriven-Input pull request.
This commit is contained in:
Dylan Wilson
2015-08-22 21:24:07 +10:00
16 changed files with 1004 additions and 56 deletions
@@ -0,0 +1,52 @@
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
namespace MonoGame.Extended.InputEvents
{
public abstract class Input
{
protected Game Game { get; set; }
protected Input(Game game)
{
Game = game;
}
/*####################################################################*/
/* Input Events */
/*####################################################################*/
public abstract void Update(GameTime gameTime);
/*####################################################################*/
/* Keyboard Events */
/*####################################################################*/
public abstract event EventHandler<KeyboardCharacterEventArgs> CharacterTyped;
public abstract event EventHandler<KeyboardKeyEventArgs> KeyDown;
public abstract event EventHandler<KeyboardKeyEventArgs> KeyUp;
/*####################################################################*/
/* Mouse Events */
/*####################################################################*/
public abstract event EventHandler<MouseEventArgs> MouseMoved;
public abstract event EventHandler<MouseEventArgs> MouseDoubleClick;
public abstract event EventHandler<MouseEventArgs> MouseDown;
public abstract event EventHandler<MouseEventArgs> MouseUp;
public abstract event EventHandler<MouseEventArgs> MouseWheel;
/*####################################################################*/
/* Touch Events */
/*####################################################################*/
public abstract event EventHandler<TouchEventArgs> TouchBegan;
public abstract event EventHandler<TouchEventArgs> TouchMoved;
public abstract event EventHandler<TouchEventArgs> TouchEnded;
public abstract event EventHandler<TouchEventArgs> TouchCancelled;
}
}
@@ -0,0 +1,23 @@
using System;
namespace Microsoft.Xna.Framework.Input
{
internal class MonoGameMouseEventArgs : MouseEventArgs
{
internal TimeSpan Time { get; set; }
internal MouseState Previous { get; private set; }
internal MouseState Current { get; private set; }
internal MonoGameMouseEventArgs(int x, int y, TimeSpan time, MouseState previous, MouseState current,
MouseButton button = MouseButton.None, int? value = null, int? delta = null)
: base(x, y, button, value, delta)
{
X = x;
Y = y;
Time = time;
Previous = previous;
Current = current;
}
}
}
@@ -0,0 +1,101 @@
using System;
using System.Linq;
namespace Microsoft.Xna.Framework.Input
{
internal class MonoGameKeyboardEvents
{
internal event EventHandler<KeyboardCharacterEventArgs> CharacterTyped;
internal event EventHandler<KeyboardKeyEventArgs> KeyPressed;
internal event EventHandler<KeyboardKeyEventArgs> KeyReleased;
private static int InitialDelay { get; set; }
private static int RepeatDelay { get; set; }
private Keys _lastKey;
private TimeSpan _lastPress;
private bool _isInitial;
private KeyboardState _previous;
public MonoGameKeyboardEvents()
{
InitialDelay = 800;
RepeatDelay = 50;
}
public void Update(GameTime gameTime)
{
var current = Keyboard.GetState();
if (!current.IsKeyDown(Keys.LeftAlt)
&& !current.IsKeyDown(Keys.RightAlt))
{
foreach (var key in Enum.GetValues(typeof (Keys))
.Cast<Keys>()
.Where(key => current.IsKeyDown(key) && _previous.IsKeyUp(key)))
{
var args = new KeyboardKeyEventArgs(key);
OnKeyPressed(this, args);
_lastKey = key;
_lastPress = gameTime.TotalGameTime;
_isInitial = true;
}
}
foreach (var key in
Enum.GetValues(typeof(Keys))
.Cast<Keys>()
.Where(key => current.IsKeyUp(key) && _previous.IsKeyDown(key)))
{
OnKeyReleased(this, new KeyboardKeyEventArgs(key));
}
var elapsedTime = (gameTime.TotalGameTime - _lastPress).TotalMilliseconds;
if (current.IsKeyDown(_lastKey) &&
((_isInitial && elapsedTime > InitialDelay) ||
(!_isInitial && elapsedTime > RepeatDelay)))
{
OnCharacterPressed(this, new KeyboardKeyEventArgs(_lastKey));
_lastPress = gameTime.TotalGameTime;
_isInitial = false;
}
_previous = current;
}
private void OnKeyPressed(object sender, KeyboardKeyEventArgs args)
{
if (KeyPressed != null)
{
KeyPressed(sender, args);
}
OnCharacterPressed(sender, args);
}
private void OnCharacterPressed(object sender, KeyboardKeyEventArgs args)
{
if (CharacterTyped == null) { return; }
var character = KeyboardUtil.ToChar(args.Key, args.Modifiers);
if (character.HasValue)
{
CharacterTyped(this, new KeyboardCharacterEventArgs(character.Value));
}
}
private void OnKeyReleased(object sender, KeyboardKeyEventArgs args)
{
if (KeyReleased != null)
{
KeyReleased(sender, args);
}
}
}
}
@@ -0,0 +1,238 @@
using System;
namespace Microsoft.Xna.Framework.Input
{
internal class MonoGameMouseEvents
{
internal event EventHandler<MouseEventArgs> ButtonReleased;
internal event EventHandler<MouseEventArgs> ButtonPressed;
internal event EventHandler<MouseEventArgs> ButtonDoubleClicked;
internal event EventHandler<MouseEventArgs> MouseMoved;
internal event EventHandler<MouseEventArgs> MouseWheelMoved;
private MouseState _previous;
private MonoGameMouseEventArgs _lastClick;
private readonly int _doubleClickMaxTimeDelta;
private readonly int _doubleClickMaxMovementDelta;
internal MonoGameMouseEvents(int doubleClickMaxTimeDelta, int doubleClickMaxMovementDelta)
{
_doubleClickMaxTimeDelta = doubleClickMaxTimeDelta;
_doubleClickMaxMovementDelta = doubleClickMaxMovementDelta;
_lastClick = new MonoGameMouseEventArgs(
-1,
-1,
new TimeSpan(),
Mouse.GetState(),
Mouse.GetState());
}
internal void Update(GameTime gameTime)
{
var current = Mouse.GetState();
// Check button press events.
if (current.LeftButton == ButtonState.Pressed
&& _previous.LeftButton == ButtonState.Released)
{
OnButtonPressed(this, new MonoGameMouseEventArgs(
current.X,
current.Y,
gameTime.TotalGameTime,
_previous,
current,
MouseButton.Left));
}
if (current.MiddleButton == ButtonState.Pressed
&& _previous.MiddleButton == ButtonState.Released)
{
OnButtonPressed(this, new MonoGameMouseEventArgs(
current.X,
current.Y,
gameTime.TotalGameTime,
_previous,
current,
MouseButton.Middle));
}
if (current.RightButton == ButtonState.Pressed
&& _previous.RightButton == ButtonState.Released)
{
OnButtonPressed(this, new MonoGameMouseEventArgs(
current.X,
current.Y,
gameTime.TotalGameTime,
_previous,
current,
MouseButton.Right));
}
if (current.XButton1 == ButtonState.Pressed
&& _previous.XButton1 == ButtonState.Released)
{
OnButtonPressed(this, new MonoGameMouseEventArgs(
current.X,
current.Y,
gameTime.TotalGameTime,
_previous,
current,
MouseButton.XButton1));
}
if (current.XButton2 == ButtonState.Pressed
&& _previous.XButton2 == ButtonState.Released)
{
OnButtonPressed(this, new MonoGameMouseEventArgs(
current.X,
current.Y,
gameTime.TotalGameTime,
_previous,
current,
MouseButton.XButton2));
}
// Check button releases.
if (current.LeftButton == ButtonState.Released
&& _previous.LeftButton == ButtonState.Pressed)
{
OnButtonReleased(this, new MonoGameMouseEventArgs(
current.X,
current.Y,
gameTime.TotalGameTime,
_previous,
current,
MouseButton.Left));
}
if (current.MiddleButton == ButtonState.Released
&& _previous.MiddleButton == ButtonState.Pressed)
{
OnButtonReleased(this, new MonoGameMouseEventArgs(
current.X,
current.Y,
gameTime.TotalGameTime,
_previous,
current,
MouseButton.Middle));
}
if (current.RightButton == ButtonState.Released
&& _previous.RightButton == ButtonState.Pressed)
{
OnButtonReleased(this, new MonoGameMouseEventArgs(
current.X,
current.Y,
gameTime.TotalGameTime,
_previous,
current,
MouseButton.Right));
}
if (current.XButton1 == ButtonState.Released
&& _previous.XButton1 == ButtonState.Pressed)
{
OnButtonReleased(this, new MonoGameMouseEventArgs(
current.X,
current.Y,
gameTime.TotalGameTime,
_previous,
current,
MouseButton.XButton1));
}
if (current.XButton2 == ButtonState.Released
&& _previous.XButton2 == ButtonState.Pressed)
{
OnButtonReleased(this, new MonoGameMouseEventArgs(
current.X,
current.Y,
gameTime.TotalGameTime,
_previous,
current,
MouseButton.XButton2));
}
// Check for any sort of mouse movement. If a button is down, it's a drag,
// otherwise it's a move.
if (_previous.X != current.X || _previous.Y != current.Y)
{
OnMouseMoved(this, new MonoGameMouseEventArgs(
current.X,
current.Y,
gameTime.TotalGameTime,
_previous,
current));
}
// Handle mouse wheel events.
if (_previous.ScrollWheelValue != current.ScrollWheelValue)
{
var value = current.ScrollWheelValue / 120;
var delta = (current.ScrollWheelValue - _previous.ScrollWheelValue) / 120;
OnMouseWheelMoved(this, new MonoGameMouseEventArgs(
current.X,
current.Y,
gameTime.TotalGameTime,
_previous,
current,
MouseButton.None,
value,
delta));
}
_previous = current;
}
private void OnButtonReleased(object sender, MonoGameMouseEventArgs args)
{
if (ButtonReleased != null)
{
ButtonReleased(sender, args);
}
}
private void OnButtonPressed(object sender, MonoGameMouseEventArgs args)
{
// If this click is within the right time and position of the last click,
// raise a double-click event as well.
if (ButtonDoubleClicked != null &&
_lastClick.Button == args.Button &&
(args.Time - _lastClick.Time).TotalMilliseconds < _doubleClickMaxTimeDelta &&
DistanceBetween(args.Current, _lastClick.Current) < _doubleClickMaxMovementDelta)
{
ButtonDoubleClicked(sender, args);
//args.Time = new TimeSpan(0);
}
else if (ButtonPressed != null)
{
ButtonPressed(sender, args);
}
_lastClick = args;
}
private static int DistanceBetween(MouseState a, MouseState b)
{
return Math.Abs(a.X - b.X) + Math.Abs(a.Y - b.Y);
}
private void OnMouseMoved(object sender, MouseEventArgs args)
{
if (MouseMoved != null)
{
MouseMoved(sender, args);
}
}
private void OnMouseWheelMoved(object sender, MouseEventArgs args)
{
if (MouseWheelMoved != null)
{
MouseWheelMoved(sender, args);
}
}
}
}
@@ -0,0 +1,70 @@
using System;
using Microsoft.Xna.Framework.Input.Touch;
namespace Microsoft.Xna.Framework.Input
{
public class MonoGameTouchEvents
{
internal event EventHandler<TouchEventArgs> TouchBegan;
internal event EventHandler<TouchEventArgs> TouchMoved;
internal event EventHandler<TouchEventArgs> TouchEnded;
internal event EventHandler<TouchEventArgs> TouchCancelled;
public void Update(GameTime gameTime)
{
TouchCollection touchCollection = TouchPanel.GetState();
foreach (TouchLocation tl in touchCollection)
{
switch (tl.State)
{
case TouchLocationState.Pressed:
OnTouchBegan(this, new TouchEventArgs(tl));
break;
case TouchLocationState.Moved:
OnTouchMoved(this, new TouchEventArgs(tl));
break;
case TouchLocationState.Released:
OnTouchEnded(this, new TouchEventArgs(tl));
break;
case TouchLocationState.Invalid:
OnTouchCancelled(this, new TouchEventArgs(tl));
break;
}
}
}
private void OnTouchBegan(object sender, TouchEventArgs args)
{
if (TouchBegan != null)
{
TouchBegan(sender, args);
}
}
private void OnTouchMoved(object sender, TouchEventArgs args)
{
if (TouchMoved != null)
{
TouchMoved(sender, args);
}
}
private void OnTouchEnded(object sender, TouchEventArgs args)
{
if (TouchEnded != null)
{
TouchEnded(sender, args);
}
}
private void OnTouchCancelled(object sender, TouchEventArgs args)
{
if (TouchCancelled != null)
{
TouchCancelled(sender, args);
}
}
}
}
@@ -0,0 +1,131 @@
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
namespace MonoGame.Extended.InputEvents
{
public sealed class MonoGameInput : Input
{
private readonly MonoGameMouseEvents _mouseEvents;
private readonly MonoGameKeyboardEvents _monoGameKeyboardEvents;
private readonly MonoGameTouchEvents _monoGameTouchEvents;
public MonoGameInput(Game game, int? doubleClickMaxTimeDelta = null,
int? doubleClickMaxMovementDelta = null) : base(game)
{
if (doubleClickMaxTimeDelta == null)
{
doubleClickMaxTimeDelta = 500; //Windows default
}
if (doubleClickMaxMovementDelta == null)
{
doubleClickMaxMovementDelta = 2; //Windows default
}
_mouseEvents = new MonoGameMouseEvents(
doubleClickMaxTimeDelta.Value,
doubleClickMaxTimeDelta.Value);
_monoGameKeyboardEvents = new MonoGameKeyboardEvents();
_monoGameTouchEvents = new MonoGameTouchEvents();
}
override public void Update(GameTime gameTime)
{
_mouseEvents.Update(gameTime);
_monoGameKeyboardEvents.Update(gameTime);
_monoGameTouchEvents.Update(gameTime);
}
/*####################################################################*/
/* Keyboard Events */
/*####################################################################*/
public override event EventHandler<KeyboardCharacterEventArgs> CharacterTyped
{
add { _monoGameKeyboardEvents.CharacterTyped += value; }
remove { _monoGameKeyboardEvents.CharacterTyped -= value; }
}
public override event EventHandler<KeyboardKeyEventArgs> KeyDown
{
add { _monoGameKeyboardEvents.KeyPressed += value; }
remove { _monoGameKeyboardEvents.KeyPressed -= value; }
}
public override event EventHandler<KeyboardKeyEventArgs> KeyUp
{
add { _monoGameKeyboardEvents.KeyReleased += value; }
remove { _monoGameKeyboardEvents.KeyReleased -= value; }
}
/*####################################################################*/
/* Mouse Events */
/*####################################################################*/
//Movement
public override event EventHandler<MouseEventArgs> MouseMoved
{
add { _mouseEvents.MouseMoved += value; }
remove { _mouseEvents.MouseMoved -= value; }
}
//Buttons
public override event EventHandler<MouseEventArgs> MouseDoubleClick
{
add { _mouseEvents.ButtonDoubleClicked += value; }
remove { _mouseEvents.ButtonDoubleClicked -= value; }
}
public override event EventHandler<MouseEventArgs> MouseDown
{
add { _mouseEvents.ButtonPressed += value; }
remove { _mouseEvents.ButtonPressed -= value; }
}
public override event EventHandler<MouseEventArgs> MouseUp
{
add { _mouseEvents.ButtonReleased += value; }
remove { _mouseEvents.ButtonReleased -= value; }
}
//Wheel
public override event EventHandler<MouseEventArgs> MouseWheel
{
add { _mouseEvents.MouseWheelMoved += value; }
remove { _mouseEvents.MouseWheelMoved -= value; }
}
/*####################################################################*/
/* Touch Events */
/*####################################################################*/
public override event EventHandler<TouchEventArgs> TouchBegan
{
add { _monoGameTouchEvents.TouchBegan += value; }
remove { _monoGameTouchEvents.TouchBegan -= value; }
}
public override event EventHandler<TouchEventArgs> TouchMoved
{
add { _monoGameTouchEvents.TouchMoved += value; }
remove { _monoGameTouchEvents.TouchMoved -= value; }
}
public override event EventHandler<TouchEventArgs> TouchEnded
{
add { _monoGameTouchEvents.TouchEnded += value; }
remove { _monoGameTouchEvents.TouchEnded -= value; }
}
public override event EventHandler<TouchEventArgs> TouchCancelled
{
add { _monoGameTouchEvents.TouchCancelled += value; }
remove { _monoGameTouchEvents.TouchCancelled -= value; }
}
}
}
@@ -0,0 +1,45 @@
# MonoGame-EventDriven-Input
This project provides event driven input for desktop MonoGame projects. The input has been designed to mimic the behavior of the Windows Message Queue as closely as possible creating as familiar as possible behavior.
## Getting Started
Using the library is very simple. Simple create an instance of the MonoGameInput object, call Update in the Game.Update function, and then subscribe to the events. You can even create multiple MonoGameInput instances as an easy way or organize different input schemes (for example one for your menu and one for gameplay input). To disable a MonoGameInput instance simply stop updating it.
```C#
Input _eventDrivenInput;
_eventDrivenInput = new MonoGameInput(this);
_eventDrivenInput.Update(gameTime);
_eventDrivenInput.KeyDown += (sender, keyDown) =>
{
//Subscribe to the events
};
```
Below are the currently available events.
```C#
public abstract event EventHandler<KeyboardCharacterEventArgs> CharacterTyped;
public abstract event EventHandler<KeyboardKeyEventArgs> KeyDown;
public abstract event EventHandler<KeyboardKeyEventArgs> KeyUp;
public abstract event EventHandler<MouseEventArgs> MouseMoved;
public abstract event EventHandler<MouseEventArgs> MouseDoubleClick;
public abstract event EventHandler<MouseEventArgs> MouseDown;
public abstract event EventHandler<MouseEventArgs> MouseUp;
public abstract event EventHandler<MouseEventArgs> MouseWheel;
public abstract event EventHandler<TouchEventArgs> TouchBegan;
public abstract event EventHandler<TouchEventArgs> TouchMoved;
public abstract event EventHandler<TouchEventArgs> TouchEnded;
public abstract event EventHandler<TouchEventArgs> TouchCancelled;
```
## Roadmap
- Move the project into [MonoGame.Extended](https://github.com/craftworkgames/MonoGame.Extended).
- Add support for subscribing event classes to provide an abstraction over the event subscription.
- Test against FNA and XNA
@@ -0,0 +1,14 @@
using System;
namespace Microsoft.Xna.Framework.Input
{
public class KeyboardCharacterEventArgs : EventArgs
{
public char Character { get; private set; }
internal KeyboardCharacterEventArgs(char character)
{
Character = character;
}
}
}
@@ -0,0 +1,30 @@
using System;
namespace Microsoft.Xna.Framework.Input
{
public class KeyboardKeyEventArgs : EventArgs
{
public Keys Key { get; private set; }
public Modifiers Modifiers { get; private set; }
protected internal KeyboardKeyEventArgs(Keys key)
{
Key = key;
var current = Keyboard.GetState();
Modifiers = Modifiers.None;
if (current.IsKeyDown(Keys.LeftControl) || current.IsKeyDown(Keys.RightControl))
{
Modifiers |= Modifiers.Control;
}
if (current.IsKeyDown(Keys.LeftShift) || current.IsKeyDown(Keys.RightShift))
{
Modifiers |= Modifiers.Shift;
}
if (current.IsKeyDown(Keys.LeftAlt) || current.IsKeyDown(Keys.RightAlt))
{
Modifiers |= Modifiers.Alt;
}
}
}
}
@@ -0,0 +1,24 @@
using System;
namespace Microsoft.Xna.Framework.Input
{
public abstract class MouseEventArgs : EventArgs
{
public int X { get; set; }
public int Y { get; set; }
public MouseButton Button { get; protected set; }
public int? Value { get; protected set; }
public int? Delta { get; protected set; }
protected internal MouseEventArgs(int x, int y, MouseButton button, int? value, int? delta)
{
X = x;
Y = y;
Button = button;
Value = value;
Delta = delta;
}
}
}
@@ -0,0 +1,35 @@
using System;
using Microsoft.Xna.Framework.Input.Touch;
namespace Microsoft.Xna.Framework.Input
{
public class TouchEventArgs : EventArgs
{
public TouchLocation TouchLocation { get; private set; }
internal TouchEventArgs (TouchLocation touchLocation)
{
TouchLocation = touchLocation;
}
public override bool Equals(System.Object obj)
{
if (obj == null) { return false; }
// If parameter cannot be cast to Point return false.
TouchEventArgs t = obj as TouchEventArgs;
if ((System.Object)t == null)
{
return false;
}
return TouchLocation.GetHashCode () == t.GetHashCode();
}
public override int GetHashCode()
{
return TouchLocation.Id;
}
}
}
@@ -0,0 +1,98 @@
namespace Microsoft.Xna.Framework.Input
{
internal static class KeyboardUtil
{
internal static char? ToChar(Keys key, Modifiers modifiers = Modifiers.None)
{
if (key == Keys.A) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'A' : 'a'; }
if (key == Keys.B) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'B' : 'b'; }
if (key == Keys.C) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'C' : 'c'; }
if (key == Keys.D) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'D' : 'd'; }
if (key == Keys.E) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'E' : 'e'; }
if (key == Keys.F) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'F' : 'f'; }
if (key == Keys.G) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'G' : 'g'; }
if (key == Keys.H) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'H' : 'h'; }
if (key == Keys.I) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'I' : 'i'; }
if (key == Keys.J) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'J' : 'j'; }
if (key == Keys.K) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'K' : 'k'; }
if (key == Keys.L) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'L' : 'l'; }
if (key == Keys.M) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'M' : 'm'; }
if (key == Keys.N) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'N' : 'n'; }
if (key == Keys.O) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'O' : 'o'; }
if (key == Keys.P) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'P' : 'p'; }
if (key == Keys.Q) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'Q' : 'q'; }
if (key == Keys.R) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'R' : 'r'; }
if (key == Keys.S) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'S' : 's'; }
if (key == Keys.T) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'T' : 't'; }
if (key == Keys.U) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'U' : 'u'; }
if (key == Keys.V) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'V' : 'v'; }
if (key == Keys.W) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'W' : 'w'; }
if (key == Keys.X) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'X' : 'x'; }
if (key == Keys.Y) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'Y' : 'y'; }
if (key == Keys.Z) { return ((modifiers & Modifiers.Shift) == Modifiers.Shift) ? 'Z' : 'z'; }
if ((key == Keys.D0 && !ShiftDown(modifiers)) || key == Keys.NumPad0) { return '0'; }
if ((key == Keys.D1 && !ShiftDown(modifiers)) || key == Keys.NumPad1) { return '1'; }
if ((key == Keys.D2 && !ShiftDown(modifiers)) || key == Keys.NumPad2) { return '2'; }
if ((key == Keys.D3 && !ShiftDown(modifiers)) || key == Keys.NumPad3) { return '3'; }
if ((key == Keys.D4 && !ShiftDown(modifiers)) || key == Keys.NumPad4) { return '4'; }
if ((key == Keys.D5 && !ShiftDown(modifiers)) || key == Keys.NumPad5) { return '5'; }
if ((key == Keys.D6 && !ShiftDown(modifiers)) || key == Keys.NumPad6) { return '6'; }
if ((key == Keys.D7 && !ShiftDown(modifiers)) || key == Keys.NumPad7) { return '7'; }
if ((key == Keys.D8 && !ShiftDown(modifiers)) || key == Keys.NumPad8) { return '8'; }
if ((key == Keys.D9 && !ShiftDown(modifiers)) || key == Keys.NumPad9) { return '9'; }
if (key == Keys.D0 && ShiftDown(modifiers)) { return ')'; }
if (key == Keys.D1 && ShiftDown(modifiers)) { return '!'; }
if (key == Keys.D2 && ShiftDown(modifiers)) { return '@'; }
if (key == Keys.D3 && ShiftDown(modifiers)) { return '#'; }
if (key == Keys.D4 && ShiftDown(modifiers)) { return '$'; }
if (key == Keys.D5 && ShiftDown(modifiers)) { return '%'; }
if (key == Keys.D6 && ShiftDown(modifiers)) { return '^'; }
if (key == Keys.D7 && ShiftDown(modifiers)) { return '&'; }
if (key == Keys.D8 && ShiftDown(modifiers)) { return '*'; }
if (key == Keys.D9 && ShiftDown(modifiers)) { return '('; }
if (key == Keys.Space) { return ' '; }
if (key == Keys.Tab) { return '\t'; }
if (key == Keys.Enter) { return (char)13; }
if (key == Keys.Back) { return (char)8; }
if (key == Keys.Add) { return '+'; }
if (key == Keys.Decimal) { return '.'; }
if (key == Keys.Divide) { return '/'; }
if (key == Keys.Multiply) { return '*'; }
if (key == Keys.OemBackslash) { return '\\'; }
if (key == Keys.OemComma && !ShiftDown(modifiers)) { return ','; }
if (key == Keys.OemComma && ShiftDown(modifiers)) { return '<'; }
if (key == Keys.OemOpenBrackets && !ShiftDown(modifiers)) { return '['; }
if (key == Keys.OemOpenBrackets && ShiftDown(modifiers)) { return '{'; }
if (key == Keys.OemCloseBrackets && !ShiftDown(modifiers)) { return ']'; }
if (key == Keys.OemCloseBrackets && ShiftDown(modifiers)) { return '}'; }
if (key == Keys.OemPeriod && !ShiftDown(modifiers)) { return '.'; }
if (key == Keys.OemPeriod && ShiftDown(modifiers)) { return '>'; }
if (key == Keys.OemPipe && !ShiftDown(modifiers)) { return '\\'; }
if (key == Keys.OemPipe && ShiftDown(modifiers)) { return '|'; }
if (key == Keys.OemPlus && !ShiftDown(modifiers)) { return '='; }
if (key == Keys.OemPlus && ShiftDown(modifiers)) { return '+'; }
if (key == Keys.OemMinus && !ShiftDown(modifiers)) { return '-'; }
if (key == Keys.OemMinus && ShiftDown(modifiers)) { return '_'; }
if (key == Keys.OemQuestion && !ShiftDown(modifiers)) { return '/'; }
if (key == Keys.OemQuestion && ShiftDown(modifiers)) { return '?'; }
if (key == Keys.OemQuotes && !ShiftDown(modifiers)) { return '\''; }
if (key == Keys.OemQuotes && ShiftDown(modifiers)) { return '"'; }
if (key == Keys.OemSemicolon && !ShiftDown(modifiers)) { return ';'; }
if (key == Keys.OemSemicolon && ShiftDown(modifiers)) { return ':'; }
if (key == Keys.OemTilde && !ShiftDown(modifiers)) { return '`'; }
if (key == Keys.OemTilde && ShiftDown(modifiers)) { return '~'; }
if (key == Keys.Subtract) { return '-'; }
return null;
}
private static bool ShiftDown(Modifiers modifiers)
{
return ((modifiers & Modifiers.Shift) == Modifiers.Shift);
}
}
}
@@ -0,0 +1,13 @@
using System;
namespace Microsoft.Xna.Framework.Input
{
[Flags]
public enum Modifiers
{
Control = 1,
Shift = 2,
Alt = 4,
None = 0
};
}
@@ -0,0 +1,12 @@
namespace Microsoft.Xna.Framework.Input
{
public enum MouseButton
{
None,
Left,
Middle,
Right,
XButton1,
XButton2
};
}
@@ -47,6 +47,19 @@
<Compile Include="Content\ContentLoader.cs" />
<Compile Include="Content\ContentManagerExtensions.cs" />
<Compile Include="Camera2D.cs" />
<Compile Include="InputEvents\Input.cs" />
<Compile Include="InputEvents\MonoGame.Input\EventArgs\MonoGameMouseEventArgs.cs" />
<Compile Include="InputEvents\MonoGame.Input\Keyboard\MonoGameMouseEvents.cs" />
<Compile Include="InputEvents\MonoGame.Input\Mouse\MonoGameMouseEvents.cs" />
<Compile Include="InputEvents\MonoGame.Input\Touch\MonoGameTouchEvents.cs" />
<Compile Include="InputEvents\MonoGameInput.cs" />
<Compile Include="InputEvents\Shared\EventArgs\KeyboardCharacterEventArgs.cs" />
<Compile Include="InputEvents\Shared\EventArgs\KeyboardKeyEventArgs.cs" />
<Compile Include="InputEvents\Shared\EventArgs\MouseEventArgs.cs" />
<Compile Include="InputEvents\Shared\EventArgs\TouchEventArgs.cs" />
<Compile Include="InputEvents\Shared\Keyboard\KeyboardUtil.cs" />
<Compile Include="InputEvents\Shared\Keyboard\Modifiers.cs" />
<Compile Include="InputEvents\Shared\Mouse\MouseButton.cs" />
<Compile Include="Sprites\SpriteExtensions.cs" />
<Compile Include="TextureAtlases\TextureAtlas.cs" />
<Compile Include="TextureAtlases\TextureAtlasReader.cs" />
@@ -77,6 +90,7 @@
</Reference>
</ItemGroup>
<ItemGroup>
<None Include="InputEvents\README.md" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
+104 -56
View File
@@ -9,6 +9,7 @@ using MonoGame.Extended.Maps.Tiled;
using MonoGame.Extended.Sprites;
using MonoGame.Extended.TextureAtlases;
using MonoGame.Extended.ViewportAdapters;
using MonoGame.Extended.InputEvents;
namespace Sandbox
{
@@ -25,11 +26,15 @@ namespace Sandbox
private Camera2D _camera;
private Texture2D _backgroundTexture;
private Sprite _sprite;
private MouseState _previousMouseState;
private ViewportAdapter _viewportAdapter;
private BitmapFont _bitmapFont;
private TiledMap _tiledMap;
private Input _eventDrivenInput;
private Vector2 _cameraDirection = Vector2.Zero;
private float _cameraRotation = 0f;
public SandboxGame()
{
_graphicsDeviceManager = new GraphicsDeviceManager(this);
@@ -55,6 +60,8 @@ namespace Sandbox
Window.AllowUserResizing = true;
Window.ClientSizeChanged += (s, e) => _viewportAdapter.OnClientSizeChanged();
SetUpInput();
base.Initialize();
}
@@ -86,59 +93,18 @@ namespace Sandbox
protected override void Update(GameTime gameTime)
{
var deltaTime = (float) gameTime.ElapsedGameTime.TotalSeconds;
_eventDrivenInput.Update(gameTime);
var deltaTime = (float) gameTime.ElapsedGameTime.TotalMilliseconds * .001f;
var keyboardState = Keyboard.GetState();
var mouseState = Mouse.GetState();
//var gamePadState = GamePad.GetState(PlayerIndex.One);
if (keyboardState.IsKeyDown(Keys.Escape))
Exit();
var up = new Vector2(0, -250);
var right = new Vector2(250, 0);
// rotation
if (keyboardState.IsKeyDown(Keys.Q))
_camera.Rotation -= deltaTime;
if (keyboardState.IsKeyDown(Keys.W))
_camera.Rotation += deltaTime;
// movement
var direction = Vector2.Zero;
if (keyboardState.IsKeyDown(Keys.Up))
direction += up * deltaTime;
if (keyboardState.IsKeyDown(Keys.Down))
direction += -up * deltaTime;
Exit();
if (keyboardState.IsKeyDown(Keys.Left))
direction += -right * deltaTime;
if (keyboardState.IsKeyDown(Keys.Right))
direction += right * deltaTime;
_camera.Move(direction);
// zoom
var scrollWheelDelta = mouseState.ScrollWheelValue - _previousScrollWheelValue;
if (scrollWheelDelta != 0)
_camera.Zoom += scrollWheelDelta * 0.0001f;
_previousScrollWheelValue = mouseState.ScrollWheelValue;
// look at
if (mouseState.LeftButton == ButtonState.Pressed && _previousMouseState.LeftButton == ButtonState.Released)
{
var p = _viewportAdapter.PointToScreen(mouseState.X, mouseState.Y);
Trace.WriteLine(string.Format("{0},{1} => {2},{3}", mouseState.X, mouseState.Y, p.X, p.Y));
}
_previousMouseState = mouseState;
_sprite.Rotation += deltaTime;
_camera.Move(_cameraDirection * deltaTime);
_camera.Rotation += _cameraRotation * deltaTime;
base.Update(gameTime);
}
@@ -153,16 +119,17 @@ namespace Sandbox
_tiledMap.Draw(_camera);
//_spriteBatch.Begin();
_spriteBatch.Begin();
//_spriteBatch.DrawString(_bitmapFont, "This is MonoGame.Extended", new Vector2(50, 50), new Color(Color.Black, 0.5f));
//_spriteBatch.DrawString(_bitmapFont, string.Format("Camera: {0}", _camera.Position), new Vector2(50, 100), Color.Black);
////_spriteBatch.DrawString(_bitmapFont,
//// "Contrary to popular belief, Lorem Ipsum is not simply random text.\n\n" +
//// "It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard " +
//// "McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin " +
//// "words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, " +
//// "discovered the undoubtable source.", new Vector2(50, 100), new Color(Color.Black, 0.5f), _viewportAdapter.VirtualWidth - 50);
//_spriteBatch.End();
//_spriteBatch.DrawString(_bitmapFont, string.Format("Camera Direction: {0}", _cameraDirection), new Vector2(50, 150), Color.Black);
//_spriteBatch.DrawString(_bitmapFont,
// "Contrary to popular belief, Lorem Ipsum is not simply random text.\n\n" +
// "It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard " +
// "McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin " +
// "words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, " +
// "discovered the undoubtable source.", new Vector2(50, 100), new Color(Color.Black, 0.5f), _viewportAdapter.VirtualWidth - 50);
_spriteBatch.End();
_spriteBatch.Begin(transformMatrix: _camera.GetViewMatrix());
_spriteBatch.Draw(_textureRegion, _sprite.GetBoundingRectangle(), Color.White);
@@ -171,5 +138,86 @@ namespace Sandbox
base.Draw(gameTime);
}
private void SetUpInput()
{
_eventDrivenInput = new MonoGameInput(this);
var up = new Vector2(0, -250);
var right = new Vector2(250, 0);
//camera movment
_eventDrivenInput.KeyDown += (sender, keyDown) =>
{
switch (keyDown.Key)
{
case Keys.Escape:
Exit();
break;
case Keys.Q:
_cameraRotation += 1;
break;
case Keys.W:
_cameraRotation -= 1;
break;
case Keys.Up:
_cameraDirection += up;
break;
case Keys.Down:
_cameraDirection += -up;
break;
case Keys.Left:
_cameraDirection += -right;
break;
case Keys.Right:
_cameraDirection += right;
break;
}
};
_eventDrivenInput.KeyUp += (sender, keyUp) =>
{
switch (keyUp.Key)
{
case Keys.Q:
_cameraRotation -= 1;
break;
case Keys.W:
_cameraRotation += 1;
break;
case Keys.Up:
_cameraDirection -= up;
break;
case Keys.Down:
_cameraDirection -= -up;
break;
case Keys.Left:
_cameraDirection -= -right;
break;
case Keys.Right:
_cameraDirection -= right;
break;
}
};
// zoom
_eventDrivenInput.MouseWheel += (sender, mouseEvent) =>
{
_camera.Zoom += mouseEvent.Delta.Value * 0.0001f;
};
// look at
_eventDrivenInput.MouseUp += (sender, mouseUp) =>
{
if (mouseUp.Button == MouseButton.Left)
{
var p = _viewportAdapter.PointToScreen(mouseUp.X, mouseUp.Y);
Trace.WriteLine(string.Format("{0},{1} => {2},{3}", mouseUp.X, mouseUp.Y, p.X, p.Y));
}
};
}
}
}