diff options
-rw-r--r-- | WindowsPhone/JoystickTest/JoystickTest/Game1.cs | 30 | ||||
-rw-r--r-- | WindowsPhone/JoystickTest/JoystickTestContent/Courier New.spritefont | 52 | ||||
-rw-r--r-- | WindowsPhone/JoystickTest/JoystickTestContent/JoystickTestContent.contentproj | 7 | ||||
-rw-r--r-- | WindowsPhone/KeyboardTest.suo | bin | 51712 -> 51712 bytes | |||
-rw-r--r-- | src/Noddybox.Emulation.Xna.Input/Joystick/JoystickDriver.cs | 283 | ||||
-rw-r--r-- | src/Noddybox.Emulation.Xna.Input/Joystick/JoystickState.cs | 14 | ||||
-rw-r--r-- | src/Noddybox.Emulation.Xna.Input/Keyboard/KeyboardDriver.cs | 26 |
7 files changed, 385 insertions, 27 deletions
diff --git a/WindowsPhone/JoystickTest/JoystickTest/Game1.cs b/WindowsPhone/JoystickTest/JoystickTest/Game1.cs index 53560a7..09cbfd8 100644 --- a/WindowsPhone/JoystickTest/JoystickTest/Game1.cs +++ b/WindowsPhone/JoystickTest/JoystickTest/Game1.cs @@ -27,6 +27,10 @@ namespace JoystickTest Texture2D background;
Texture2D button;
Texture2D joystick;
+ SpriteFont font;
+
+ string digitalState = "No event";
+ string analogueState = "No event";
public Game1()
{
@@ -64,6 +68,7 @@ namespace JoystickTest {
spriteBatch = new SpriteBatch(GraphicsDevice);
+ font = Content.Load<SpriteFont>("Courier New");
background = Content.Load<Texture2D>("joystick_background");
joystick = Content.Load<Texture2D>("joystick");
button = Content.Load<Texture2D>("button");
@@ -72,11 +77,17 @@ namespace JoystickTest digital = new JoystickDriver(manager, GraphicsDevice, JoystickType.Digital, background, joystick, button,
Vector2.Zero, new Vector2(100), new Vector2[2] {new Vector2(300, 50), new Vector2(300, 150)},
- 10, 100);
+ 25, 50);
analogue = new JoystickDriver(manager, GraphicsDevice, JoystickType.Analogue, background, joystick, button,
new Vector2(0, 300), new Vector2(100), new Vector2[1] {new Vector2(300, 150)},
- 10, 100);
+ 5, 50);
+
+ digital.LockType = JoystickLock.EightWay;
+ analogue.LockType = JoystickLock.EightWay;
+
+ digital.DigitalEvent += DigitalHandler;
+ analogue.AnalogueEvent += AnalogueHandler;
}
/// <summary>
@@ -105,16 +116,29 @@ namespace JoystickTest /// <param name="gameTime">Provides a snapshot of timing values.</param>
protected override void Draw(GameTime gameTime)
{
- GraphicsDevice.Clear(Color.White);
+ GraphicsDevice.Clear(Color.Black);
spriteBatch.Begin();
digital.Draw(spriteBatch);
analogue.Draw(spriteBatch);
+ spriteBatch.DrawString(font, digitalState, new Vector2(0, 700), Color.Yellow, 0f, Vector2.Zero, 0.5f, SpriteEffects.None, 1f);
+ spriteBatch.DrawString(font, analogueState, new Vector2(0, 720), Color.Green, 0f, Vector2.Zero, 0.5f, SpriteEffects.None, 1f);
+
spriteBatch.End();
base.Draw(gameTime);
}
+
+ private void DigitalHandler(object sender, JoystickDriver.DigitalJoystickEventArgs e)
+ {
+ digitalState = String.Format("{0} {1} {2}", e.State, e.Buttons[0], e.Buttons[1]);
+ }
+
+ private void AnalogueHandler(object sender, JoystickDriver.AnalogueJoystickEventArgs e)
+ {
+ analogueState = String.Format("{0} {1}", e.State, e.Buttons[0]);
+ }
}
}
diff --git a/WindowsPhone/JoystickTest/JoystickTestContent/Courier New.spritefont b/WindowsPhone/JoystickTest/JoystickTestContent/Courier New.spritefont new file mode 100644 index 0000000..ebefa68 --- /dev/null +++ b/WindowsPhone/JoystickTest/JoystickTestContent/Courier New.spritefont @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?>
+<!--
+This file contains an xml description of a font, and will be read by the XNA
+Framework Content Pipeline. Follow the comments to customize the appearance
+of the font in your game, and to change the characters which are available to draw
+with.
+-->
+<XnaContent xmlns:Graphics="Microsoft.Xna.Framework.Content.Pipeline.Graphics">
+ <Asset Type="Graphics:FontDescription">
+
+ <!--
+ Modify this string to change the font that will be imported.
+ -->
+ <FontName>Courier New</FontName>
+
+ <!--
+ Size is a float value, measured in points. Modify this value to change
+ the size of the font.
+ -->
+ <Size>28</Size>
+
+ <!--
+ Spacing is a float value, measured in pixels. Modify this value to change
+ the amount of spacing in between characters.
+ -->
+ <Spacing>2</Spacing>
+
+ <!--
+ Style controls the style of the font. Valid entries are "Regular", "Bold", "Italic",
+ and "Bold, Italic", and are case sensitive.
+ -->
+ <Style>Regular</Style>
+
+ <!--
+ CharacterRegions control what letters are available in the font. Every
+ character from Start to End will be built and made available for drawing. The
+ default range is from 32 to 127, which is the basic Latin character set. The
+ characters are ordered according to the Unicode standard.
+ Change these regions to make more or fewer letters available. To save
+ graphics memory and decrease build time, try to use as few letters as possible.
+ You can specify additional regions by adding more <CharacterRegion> tags.
+ Alternatively, you can use a custom processor to add specific characters. See
+ the documentation for more information.
+ -->
+ <CharacterRegions>
+ <CharacterRegion>
+ <Start> </Start>
+ <End>~</End>
+ </CharacterRegion>
+ </CharacterRegions>
+ </Asset>
+</XnaContent>
\ No newline at end of file diff --git a/WindowsPhone/JoystickTest/JoystickTestContent/JoystickTestContent.contentproj b/WindowsPhone/JoystickTest/JoystickTestContent/JoystickTestContent.contentproj index abe9430..ce74723 100644 --- a/WindowsPhone/JoystickTest/JoystickTestContent/JoystickTestContent.contentproj +++ b/WindowsPhone/JoystickTest/JoystickTestContent/JoystickTestContent.contentproj @@ -46,6 +46,13 @@ <Processor>TextureProcessor</Processor>
</Compile>
</ItemGroup>
+ <ItemGroup>
+ <Compile Include="Courier New.spritefont">
+ <Name>Courier New</Name>
+ <Importer>FontDescriptionImporter</Importer>
+ <Processor>FontDescriptionProcessor</Processor>
+ </Compile>
+ </ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\XNA Game Studio\$(XnaFrameworkVersion)\Microsoft.Xna.GameStudio.ContentPipeline.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
diff --git a/WindowsPhone/KeyboardTest.suo b/WindowsPhone/KeyboardTest.suo Binary files differindex bfb7f24..d51930b 100644 --- a/WindowsPhone/KeyboardTest.suo +++ b/WindowsPhone/KeyboardTest.suo diff --git a/src/Noddybox.Emulation.Xna.Input/Joystick/JoystickDriver.cs b/src/Noddybox.Emulation.Xna.Input/Joystick/JoystickDriver.cs index dc83831..450113b 100644 --- a/src/Noddybox.Emulation.Xna.Input/Joystick/JoystickDriver.cs +++ b/src/Noddybox.Emulation.Xna.Input/Joystick/JoystickDriver.cs @@ -45,7 +45,7 @@ namespace Noddybox.Emulation.Xna.Input.Joystick public bool[] Buttons {get; private set;}
- private DigitalJoystickEventArgs(DigitalJoystickState state, bool[] buttons)
+ public DigitalJoystickEventArgs(DigitalJoystickState state, bool[] buttons)
{
State = state;
Buttons = buttons;
@@ -64,7 +64,7 @@ namespace Noddybox.Emulation.Xna.Input.Joystick public bool[] Buttons {get; private set;}
- private AnalogueJoystickEventArgs(Vector2 state, bool[] buttons)
+ public AnalogueJoystickEventArgs(Vector2 state, bool[] buttons)
{
State = state;
Buttons = buttons;
@@ -77,6 +77,7 @@ namespace Noddybox.Emulation.Xna.Input.Joystick private InputManager manager;
private bool subscribed;
+ private JoystickType joystickType;
private Texture2D backgroundImage;
private Texture2D joystickImage;
@@ -84,12 +85,16 @@ namespace Noddybox.Emulation.Xna.Input.Joystick private DigitalJoystickState digital;
private Vector2 analogue;
+ private Vector2 contact;
+ private int stickId;
private bool[] button;
+ private int[] buttonId;
private Vector2 backgroundPosition;
private Vector2 joystickPosition;
private Vector2[] buttonPositions;
private float deadzone;
+ private bool deadzoneBreached;
private float stickSize;
private int numButtons;
@@ -100,37 +105,197 @@ namespace Noddybox.Emulation.Xna.Input.Joystick private JoystickLock joylock;
+ private Vector2[] digitalPositions;
+ private DigitalJoystickState[] digitalAngles;
+
#endregion
#region Private members
/// <summary>
+ /// Update the analogue position with the passed state. This also applies the joylock clamp.
+ /// </summary>
+ /// <param name="v">The touch screen location.</param>
+ /// <returns>True if the state was changed.</returns>
+ private bool UpdatePosition(Vector2 v)
+ {
+ v -= contact;
+
+ switch(joylock)
+ {
+ case JoystickLock.TwoWayVertical:
+ v.X = 0;
+ break;
+
+ case JoystickLock.TwoWayHorizontal:
+ v.Y = 0;
+ break;
+
+ case JoystickLock.FourWay:
+ if (Math.Abs(v.Y) > Math.Abs(v.X))
+ {
+ v.X = 0;
+ }
+ else
+ {
+ v.Y = 0;
+ }
+ break;
+
+ case JoystickLock.EightWay:
+ break;
+ }
+
+ if (v.Length() > stickSize)
+ {
+ v.Normalize();
+ v *= stickSize;
+ }
+
+ if (v != analogue)
+ {
+ analogue = v;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Update the digital position with the new analogue state.
+ /// </summary>
+ /// <param name="v"></param>
+ /// <returns>True if the state was changed.</returns>
+ private bool UpdatePosition()
+ {
+ DigitalJoystickState newState = DigitalJoystickState.Centre;
+
+ if (analogue.Length() > deadzone)
+ {
+ float angle = MathHelper.ToDegrees((float)Math.Atan2(analogue.Y, analogue.X)) + 22.5f;
+
+ while (angle < 0)
+ {
+ angle += 360;
+ }
+
+ System.Diagnostics.Debug.WriteLine("original angle = {0}", angle);
+
+ angle = Math.Min(angle / 45, 7);
+
+ newState = digitalAngles[(int)angle];
+ System.Diagnostics.Debug.WriteLine("calced angle = {0} / {1}", angle, newState);
+ }
+
+ if (newState != digital)
+ {
+ digital = newState;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ /// <summary>
/// Updates the joystick.
/// </summary>
- public void TouchScreenHandler(object sender, InputManager.TouchLocationEventArgs e)
+ private void TouchScreenHandler(object sender, InputManager.TouchLocationEventArgs e)
{
- if (e.Location.State == TouchLocationState.Pressed)
+ bool stateChanged = false;
+
+ // Handle release of stick or buttons
+ //
+ if (e.Location.State == TouchLocationState.Released)
+ {
+ if (stickId == e.Location.Id)
+ {
+ stickId = 0;
+ digital = DigitalJoystickState.Centre;
+ analogue = Vector2.Zero;
+ stateChanged = true;
+ e.Handled = true;
+ }
+ else
+ {
+ for(int f = 0; !e.Handled && f < numButtons; f++)
+ {
+ if (buttonId[f] == e.Location.Id)
+ {
+ buttonId[f] = 0;
+ button[f] = false;
+ stateChanged = true;
+ e.Handled = true;
+ }
+ }
+ }
+ }
+
+ // Handle hold of stick
+ //
+ if (e.Location.State == TouchLocationState.Moved && e.Location.Id == stickId)
{
- for(int f = 0; !e.Handled && f < numButtons; f++)
+ e.Handled = true;
+
+ if (!deadzoneBreached)
{
- if ((buttonPositions[f] - e.Location.Position).Length() < buttonSize)
+ float l = (contact - e.Location.Position).Length();
+
+ if (l > deadzone)
{
- e.Handled = true;
- button[f] = true;
+ deadzoneBreached = true;
}
}
+
+ if (joystickType == JoystickType.Digital && deadzoneBreached && UpdatePosition(e.Location.Position))
+ {
+ stateChanged = UpdatePosition();
+ }
+ else if (joystickType == JoystickType.Analogue && deadzoneBreached)
+ {
+ stateChanged = UpdatePosition(e.Location.Position);
+ }
}
- else if (e.Location.State == TouchLocationState.Released)
+
+ // Handle touch of stick or buttons
+ //
+ if (e.Location.State == TouchLocationState.Pressed)
{
- for(int f = 0; !e.Handled && f < numButtons; f++)
+ float l = (joystickPosition - e.Location.Position).Length();
+
+ if (l < joystickSize)
{
- if ((buttonPositions[f] - e.Location.Position).Length() < buttonSize)
+ contact = e.Location.Position;
+ stickId = e.Location.Id;
+ deadzoneBreached = false;
+ e.Handled = true;
+ }
+ else
+ {
+ for(int f = 0; !e.Handled && f < numButtons; f++)
{
- e.Handled = true;
- button[f] = false;
+ if ((buttonPositions[f] - e.Location.Position).Length() < buttonSize)
+ {
+ e.Handled = true;
+ button[f] = true;
+ buttonId[f] = e.Location.Id;
+ stateChanged = true;
+ }
}
}
}
+
+ if (stateChanged && joystickType == JoystickType.Digital && DigitalEvent != null)
+ {
+ DigitalEvent(this, new DigitalJoystickEventArgs(digital, button));
+ }
+ else if (stateChanged && joystickType == JoystickType.Analogue && AnalogueEvent != null)
+ {
+ AnalogueEvent(this, new AnalogueJoystickEventArgs(analogue, button));
+ }
}
#endregion
@@ -138,18 +303,53 @@ namespace Noddybox.Emulation.Xna.Input.Joystick #region Public members
/// <summary>
- /// Stops consuming inputs.
+ /// Set the type of joystick lock.
/// </summary>
- public void StopJoytstickUpdates()
+ public JoystickLock LockType {set {joylock = value;}}
+
+
+ /// <summary>
+ /// Stops consuming inputs and resets joystick and fire buttons.
+ /// </summary>
+ /// <param name="generateEvents">Generates events for cleared state.</param>
+ public void StopJoytstickUpdates(bool generateEvents)
{
if (subscribed)
{
manager.TouchEvent -= TouchScreenHandler;
subscribed = false;
+
+ digital = DigitalJoystickState.Centre;
+ analogue = Vector2.Zero;
+ stickId = 0;
+ deadzoneBreached = false;
+
+ for(int f = 0; f < numButtons; f++)
+ {
+ button[f] = false;
+ buttonId[f] = 0;
+ }
+
+ if (generateEvents && joystickType == JoystickType.Digital && DigitalEvent != null)
+ {
+ DigitalEvent(this, new DigitalJoystickEventArgs(digital, button));
+ }
+ else if (generateEvents && joystickType == JoystickType.Analogue && AnalogueEvent != null)
+ {
+ AnalogueEvent(this, new AnalogueJoystickEventArgs(analogue, button));
+ }
}
}
/// <summary>
+ /// Stops consuming inputs and resets joystick and fire buttons. Generates events for the cleared state.
+ /// </summary>
+ public void StopJoytstickUpdates()
+ {
+ StopJoytstickUpdates(true);
+ }
+
+ /// <summary>
/// Starts consuming inputs.
/// </summary>
public void StartJoystickUpdates()
@@ -169,8 +369,16 @@ namespace Noddybox.Emulation.Xna.Input.Joystick {
spriteBatch.Draw(backgroundImage, backgroundPosition, Color.White);
- spriteBatch.Draw(joystickImage, joystickPosition + analogue,
- null, Color.White, 0f, joystickOffset, 1f, SpriteEffects.None, 0f);
+ if (joystickType == JoystickType.Digital)
+ {
+ spriteBatch.Draw(joystickImage, joystickPosition + digitalPositions[(int)digital],
+ null, Color.White, 0f, joystickOffset, 1f, SpriteEffects.None, 0f);
+ }
+ else
+ {
+ spriteBatch.Draw(joystickImage, joystickPosition + analogue,
+ null, Color.White, 0f, joystickOffset, 1f, SpriteEffects.None, 0f);
+ }
for(int f = 0; f < numButtons; f++)
{
@@ -183,6 +391,10 @@ namespace Noddybox.Emulation.Xna.Input.Joystick #region Events
+ public EventHandler<DigitalJoystickEventArgs> DigitalEvent;
+
+ public EventHandler<AnalogueJoystickEventArgs> AnalogueEvent;
+
#endregion
#region Constructors
@@ -207,6 +419,7 @@ namespace Noddybox.Emulation.Xna.Input.Joystick float deadzone, float stickSize)
{
this.manager = manager;
+ this.joystickType = joystickType;
this.backgroundImage = backgroundImage;
this.joystickImage = joystickImage;
this.buttonImage = buttonImage;
@@ -224,6 +437,7 @@ namespace Noddybox.Emulation.Xna.Input.Joystick this.numButtons = buttonPositions.Length;
this.button = new bool[numButtons];
+ this.buttonId = new int[numButtons];
this.buttonPositions = new Vector2[numButtons];
for(int f = 0; f < numButtons; f++)
@@ -239,12 +453,47 @@ namespace Noddybox.Emulation.Xna.Input.Joystick }
this.deadzone = deadzone;
+ this.deadzoneBreached = false;
this.stickSize = stickSize;
this.digital = DigitalJoystickState.Centre;
this.joylock = JoystickLock.EightWay;
this.analogue = Vector2.Zero;
+ this.digitalPositions = new Vector2[16];
+
+ this.digitalPositions[(int)DigitalJoystickState.Centre] = Vector2.Zero;
+
+ this.digitalPositions[(int)DigitalJoystickState.Up] = new Vector2(0, -stickSize);
+ this.digitalPositions[(int)DigitalJoystickState.Down] = new Vector2(0, stickSize);
+ this.digitalPositions[(int)DigitalJoystickState.Left] = new Vector2(-stickSize, 0);
+ this.digitalPositions[(int)DigitalJoystickState.Right] = new Vector2(stickSize, 0);
+
+ this.digitalPositions[(int)DigitalJoystickState.UpLeft] = new Vector2(-stickSize, -stickSize);
+ this.digitalPositions[(int)DigitalJoystickState.UpRight] = new Vector2(stickSize, -stickSize);
+ this.digitalPositions[(int)DigitalJoystickState.DownLeft] = new Vector2(-stickSize, stickSize);
+ this.digitalPositions[(int)DigitalJoystickState.DownRight] = new Vector2(stickSize, stickSize);
+
+ this.digitalAngles = new DigitalJoystickState[8]
+ {
+ //DigitalJoystickState.Up,
+ //DigitalJoystickState.UpRight,
+ //DigitalJoystickState.Right,
+ //DigitalJoystickState.DownRight,
+ //DigitalJoystickState.Down,
+ //DigitalJoystickState.DownLeft,
+ //DigitalJoystickState.Left,
+ //DigitalJoystickState.UpLeft
+ DigitalJoystickState.Right,
+ DigitalJoystickState.DownRight,
+ DigitalJoystickState.Down,
+ DigitalJoystickState.DownLeft,
+ DigitalJoystickState.Left,
+ DigitalJoystickState.UpLeft,
+ DigitalJoystickState.Up,
+ DigitalJoystickState.UpRight
+ };
+
StartJoystickUpdates();
}
diff --git a/src/Noddybox.Emulation.Xna.Input/Joystick/JoystickState.cs b/src/Noddybox.Emulation.Xna.Input/Joystick/JoystickState.cs index 3933127..5c23313 100644 --- a/src/Noddybox.Emulation.Xna.Input/Joystick/JoystickState.cs +++ b/src/Noddybox.Emulation.Xna.Input/Joystick/JoystickState.cs @@ -31,11 +31,15 @@ namespace Noddybox.Emulation.Xna.Input.Joystick [Flags]
public enum DigitalJoystickState
{
- Centre = 0x00,
- Up = 0x01,
- Down = 0x02,
- Left = 0x04,
- Right = 0x08
+ Centre = 0x00,
+ Up = 0x01,
+ Down = 0x02,
+ Left = 0x04,
+ Right = 0x08,
+ UpLeft = Up | Left,
+ UpRight = Up | Right,
+ DownLeft = Down | Left,
+ DownRight = Down | Right
}
/// <summary>
diff --git a/src/Noddybox.Emulation.Xna.Input/Keyboard/KeyboardDriver.cs b/src/Noddybox.Emulation.Xna.Input/Keyboard/KeyboardDriver.cs index 4fa265a..6379dd8 100644 --- a/src/Noddybox.Emulation.Xna.Input/Keyboard/KeyboardDriver.cs +++ b/src/Noddybox.Emulation.Xna.Input/Keyboard/KeyboardDriver.cs @@ -153,18 +153,40 @@ namespace Noddybox.Emulation.Xna.Input.Keyboard #region Public members
/// <summary>
- /// Stops consuming inputs.
+ /// Stops consuming inputs and releases all keys.
/// </summary>
- public void StopKeyboardUpdates()
+ /// <param name="generateEvents">Generates events for cleared keys.</param>
+ public void StopKeyboardUpdates(bool generateEvents)
{
if (subscribed)
{
manager.TouchEvent -= TouchScreenHandler;
subscribed = false;
+
+ foreach (KeyState key in keymapState)
+ {
+ if (key.IsPressed)
+ {
+ key.IsPressed = false;
+
+ if (generateEvents && KeyEvent != null)
+ {
+ KeyEvent(this, new KeyPressEventArgs() {Key = key.Symbol, Pressed = key.IsPressed});
+ }
+ }
+ }
}
}
/// <summary>
+ /// Stops consuming inputs and releases all keys. Generates events for released keys.
+ /// </summary>
+ public void StopKeyboardUpdates()
+ {
+ StopKeyboardUpdates(true);
+ }
+
+ /// <summary>
/// Starts consuming inputs.
/// </summary>
public void StartKeyboardUpdates()
|