// This file is part of the Noddybox.Emulation C# suite. // // Noddybox.Emulation is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Noddybox.Emulation is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Noddybox.Emulation. If not, see . // // Copyright (c) 2012 Ian Cowburn // using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input.Touch; namespace Noddybox.Emulation.Xna.Input.Joystick { /// /// Displays and drives the joystick. Unlike the keyboard this is not /// not done event driven, but as a clasic Joystick interface. /// public class JoystickDriver { #region Event arguments /// /// Event data when the digital joystick state changes /// public class DigitalJoystickEventArgs : EventArgs { /// /// The joystick state. /// public DigitalJoystickState State {get; private set;} public bool[] Buttons {get; private set;} private DigitalJoystickEventArgs(DigitalJoystickState state, bool[] buttons) { State = state; Buttons = buttons; } } /// /// Event data when the analogue joystick state changes /// public class AnalogueJoystickEventArgs : EventArgs { /// /// The joystick state. /// public Vector2 State {get; private set;} public bool[] Buttons {get; private set;} private AnalogueJoystickEventArgs(Vector2 state, bool[] buttons) { State = state; Buttons = buttons; } } #endregion #region Private data private InputManager manager; private bool subscribed; private Texture2D backgroundImage; private Texture2D joystickImage; private Texture2D buttonImage; private DigitalJoystickState digital; private Vector2 analogue; private bool[] button; private Vector2 backgroundPosition; private Vector2 joystickPosition; private Vector2[] buttonPositions; private float deadzone; private float stickSize; private int numButtons; private Vector2 joystickOffset; private Vector2 buttonOffset; private int joystickSize; private int buttonSize; private JoystickLock joylock; #endregion #region Private members /// /// Updates the joystick. /// public void TouchScreenHandler(object sender, InputManager.TouchLocationEventArgs e) { if (e.Location.State == TouchLocationState.Pressed) { for(int f = 0; !e.Handled && f < numButtons; f++) { if ((buttonPositions[f] - e.Location.Position).Length() < buttonSize) { e.Handled = true; button[f] = true; } } } else if (e.Location.State == TouchLocationState.Released) { for(int f = 0; !e.Handled && f < numButtons; f++) { if ((buttonPositions[f] - e.Location.Position).Length() < buttonSize) { e.Handled = true; button[f] = false; } } } } #endregion #region Public members /// /// Stops consuming inputs. /// public void StopJoytstickUpdates() { if (subscribed) { manager.TouchEvent -= TouchScreenHandler; subscribed = false; } } /// /// Starts consuming inputs. /// public void StartJoystickUpdates() { if (!subscribed) { manager.TouchEvent += TouchScreenHandler; subscribed = true; } } /// /// Draw the joystick /// /// public void Draw(SpriteBatch spriteBatch) { spriteBatch.Draw(backgroundImage, backgroundPosition, Color.White); spriteBatch.Draw(joystickImage, joystickPosition + analogue, null, Color.White, 0f, joystickOffset, 1f, SpriteEffects.None, 0f); for(int f = 0; f < numButtons; f++) { spriteBatch.Draw(buttonImage, buttonPositions[f], null, button[f] ? Color.LightGray : Color.White, 0f, buttonOffset, button[f] ? 0.9f : 1f, SpriteEffects.None, 0f); } } #endregion #region Events #endregion #region Constructors /// /// Constructor. /// /// The input manager to attach to. /// The graphics device to associate textures with. /// The type of joystick. /// The image for the joystick background. /// The image for the joystick knob. /// The image for a joystick button. /// Where to draw and offset the joystick background to. /// Where to centre the joystick. Note this is absolute. /// Positions for the buttons. /// Deadzone radius where joystick movement is not picked up. /// The maximum radius that the joystick can move. public JoystickDriver(InputManager manager, GraphicsDevice graphics, JoystickType joystickType, Texture2D backgroundImage, Texture2D joystickImage, Texture2D buttonImage, Vector2 backgroundPosition, Vector2 joystickPosition, Vector2[] buttonPositions, float deadzone, float stickSize) { this.manager = manager; this.backgroundImage = backgroundImage; this.joystickImage = joystickImage; this.buttonImage = buttonImage; this.backgroundPosition = backgroundPosition; this.joystickPosition = joystickPosition + backgroundPosition; this.joystickSize = Math.Min(joystickImage.Width, joystickImage.Height) / 2; this.joystickOffset = new Vector2(joystickImage.Width / 2f, joystickImage.Height / 2f); if (buttonImage != null) { this.buttonSize = Math.Min(buttonImage.Width, buttonImage.Height) / 2; this.buttonOffset = new Vector2(buttonImage.Width / 2f, buttonImage.Height / 2f); this.numButtons = buttonPositions.Length; this.button = new bool[numButtons]; this.buttonPositions = new Vector2[numButtons]; for(int f = 0; f < numButtons; f++) { this.buttonPositions[f] = backgroundPosition + buttonPositions[f] + buttonOffset; } } else { this.buttonSize = 0; this.buttonOffset = Vector2.Zero; this.numButtons = 0; } this.deadzone = deadzone; this.stickSize = stickSize; this.digital = DigitalJoystickState.Centre; this.joylock = JoystickLock.EightWay; this.analogue = Vector2.Zero; StartJoystickUpdates(); } #endregion } }