using System; using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input; namespace TrueCraft.Client.Input { /// /// Encapsulates keyboard input in an event-driven manner. /// public sealed class KeyboardComponent : GameComponent { /// /// Raised when a key for this keyboard component is pressed. /// public event EventHandler KeyDown; /// /// Raised when a key for this keyboard component is released. /// public event EventHandler KeyUp; /// /// Gets the state for this keyboard component. /// public KeyboardState State { get; private set; } /// /// Creates a new keyboard component. /// /// The parent game for the component. public KeyboardComponent(Game game) : base(game) { } /// /// Initializes this keyboard component. /// public override void Initialize() { State = Keyboard.GetState(); base.Initialize(); } /// /// Updates this keyboard component. /// /// The game time for the update. public override void Update(GameTime gameTime) { var newState = Keyboard.GetState(); Process(newState, State); State = newState; base.Update(gameTime); } /// /// Processes a change between two states. /// /// The new state. /// The old state. private void Process(KeyboardState newState, KeyboardState oldState) { var currentKeys = newState.GetPressedKeys(); var lastKeys = oldState.GetPressedKeys(); // LINQ was a saviour here. var pressed = currentKeys.Except(lastKeys); var unpressed = lastKeys.Except(currentKeys); foreach (var key in pressed) { var args = new KeyboardKeyEventArgs(key, true); if (KeyDown != null) KeyDown(this, args); } foreach (var key in unpressed) { var args = new KeyboardKeyEventArgs(key, false); if (KeyUp != null) KeyUp(this, args); } } /// /// Called when this keyboard component is being disposed of. /// /// Whether Dispose() called this method. protected override void Dispose(bool disposing) { if (disposing) { KeyDown = null; KeyUp = null; } base.Dispose(disposing); } } }