代码改变世界

SilverXna初体验:通用键盘输入设备

2011-12-13 20:29  独孤残云  阅读(1566)  评论(0编辑  收藏  举报

继承上一节的设计思路,本节我们来补全SilverXna键盘输入设备的实现。

首先依然是常量和枚举定义:

InputTypes.cs
/*-------------------------------------

代码清单:InputTypes.cs
来自:
http://www.cnblogs.com/kenkao

-------------------------------------
*/

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Microsoft.Xna.Framework.Input
{
    // 鼠标设备动作
    public enum MouseAction
    {
        None,

        MouseLeftButtonDown,
        MouseLeftButtonUp,
        MouseRightButtonDown,
        MouseRightButtonUp,

        LostMouseCapture,
        MouseEnter,
        MouseLeave,
        MouseMove,

        MouseWheel
    }

    // 键盘设备动作
    public enum KeyboardAction
    {
        None,

        KeyDown,
        KeyUp
    }

    // 鼠标键状态
    public enum ButtonState
    {
        Released = 0,
        Pressed = 1
    }

    // 键盘键状态
    public enum KeyState
    {
        Up = 0,
        Down = 1
    }

    // 鼠标设备委托定义
    public delegate void MouseButtonHandler(MouseAction act, MouseButtonEventArgs e);
    public delegate void MouseCommonHandler(MouseAction act, MouseEventArgs e);
    public delegate void MouseWheelHandler(MouseAction act, MouseWheelEventArgs e);

    // 键盘设备委托定义
    public delegate void KeyboardHandler(KeyboardAction act, KeyEventArgs e);
}

接下来是键盘设备状态的定义,思路仿前一节的MouseState,参看Xna内部的定义亦可:

KeyboardState.cs
/*-------------------------------------

代码清单:KeyboardState.cs
来自:
http://www.cnblogs.com/kenkao

-------------------------------------
*/

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Microsoft.Xna.Framework.Input
{
    /// <summary>
    
/// 键盘设备状态
    
/// </summary>
    public class KeyboardState
    {
        // 键位状态缓冲数组
        KeyState[] _KeyStateBuffer;

        // 构造函数
        public KeyboardState(KeyState[] KeyStateBuffer)
        {
            _KeyStateBuffer = KeyStateBuffer;
        }

        // 获得单键状态
        public KeyState this[Key key]
        {
            get
            {
                return _KeyStateBuffer[(int)key];
            }
        }

        // 检测单键是否按下
        public bool IsKeyDown(Key key)
        {
            return _KeyStateBuffer[(int)key] == KeyState.Down;
        }

        // 检测单键是否弹起
        public bool IsKeyUp(Key key)
        {
            return _KeyStateBuffer[(int)key] == KeyState.Up;
        }

        // 重载 != 运算符
        public static bool operator !=(KeyboardState a, KeyboardState b)
        {
            return !(a == b);
        }

        // 重载 == 运算符
        public static bool operator ==(KeyboardState a, KeyboardState b)
        {
            return a._KeyStateBuffer == b._KeyStateBuffer;
        }
    }
}

之后我们收集Silverlight控件的键盘响应事件,还原键盘设备输入状态即可。

Silverlight控件通用的键盘事件只有键位按下与弹起两种,因此实现起来相对简单。我们只需侦听并存储256个键位全部的按下和弹起状态即可。

KeyboardInput.cs
/*-------------------------------------

代码清单:KeyboardInput.cs
来自:
http://www.cnblogs.com/kenkao

-------------------------------------
*/

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Microsoft.Xna.Framework.Input
{
    public class KeyboardInput
    {
        // 256个键位状态
        static KeyState[] _KeyStateBuffer = new KeyState[256];

        // 监听根容器
        static UIElement _Handle;
        static public UIElement Handle
        { get { return _Handle; } }

        // 键盘事件定义
        static public event KeyboardHandler KeyboardEvent;

        // 初始化键盘输入设备
        static public void InitDevice(UIElement handle)
        {
            _Handle = handle;
            _Handle.KeyDown += new KeyEventHandler(_Handle_KeyDown);
            _Handle.KeyUp += new KeyEventHandler(_Handle_KeyUp);
        }

        // 获得键盘设备状态
        static public KeyboardState GetState()
        {
            return new KeyboardState((KeyState[])_KeyStateBuffer.Clone());
        }

        // 设备内置键位按下事件处理
        static void _Handle_KeyDown(object sender, KeyEventArgs e)
        {
            // 重置键位状态
            int KeyIndex = (int)e.Key;
            _KeyStateBuffer[KeyIndex] = KeyState.Down;
            // 支持外链键位按下事件
            if (KeyboardEvent != null)
                KeyboardEvent.Invoke(KeyboardAction.KeyDown, e);
        }

        // 设备内置键位弹起事件
        static void _Handle_KeyUp(object sender, KeyEventArgs e)
        {
            // 重置键位状态
            int KeyIndex = (int)e.Key;
            _KeyStateBuffer[KeyIndex] = KeyState.Up;
            // 支持外链键位弹起事件
            if (KeyboardEvent != null)
                KeyboardEvent.Invoke(KeyboardAction.KeyUp, e);
        }
    }
}

思路上完全仿上一节的MouseInput。然后我们将Silverlight默认根容器捆绑给构建好的键盘输入设备。

/*-------------------------------------

代码清单:MainPage.xaml.cs
来自:
http://www.cnblogs.com/kenkao

-------------------------------------
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace SilverXna
{
    public partial class MainPage : UserControl
    {
        Game _Game;
        public MainPage()
        {
            InitializeComponent();
            _Game = new Game(_GameSurface);
            // 初始化键盘、鼠标输入设备
            KeyboardInput.InitDevice(this);
            MouseInput.InitDevice(this);
        }
    }
}

最后是我们的主体代码:

Game.cs
/*-------------------------------------

代码清单:Game.cs
来自:
http://www.cnblogs.com/kenkao

-------------------------------------
*/

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using System.Windows.Media.Animation;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System.IO;

namespace SilverXna
{
    public class Game : SilverGame
    {
        SpriteBatch _SpriteBatch;
        Texture2D texture;

        public Game(DrawingSurface GameSurface)
            : base(GameSurface)
        { }

        public override void Initialize()
        {
            base.Initialize();
        }

        public override void LoadContent()
        {
            _SpriteBatch = new SpriteBatch(this);

            Stream imageStream = Content.OpenResourceStream("SilverXna","Content/SLXNA.png");
            texture = Content.LoadTexture2D(imageStream);
            base.LoadContent();
        }

        public override void UnloadContent()
        {
            base.UnloadContent();
        }

        Vector2 pos = new Vector2(100100);
        public override void Update(TimeSpan DeltaTime, TimeSpan TotalTime)
        {
            // 获得鼠标设备状态
            MouseState mouseState = MouseInput.GetState();
            // 更新纹理位置到鼠标左键单击点
            if (mouseState.LeftButton == ButtonState.Pressed)
            {
                pos = new Vector2((float)mouseState.X, (float)mouseState.Y);
            }
            // 获得键盘设备状态
            KeyboardState keyboardState = KeyboardInput.GetState();
            // 如果D键按下,则纹理向右移动一个像素
            if (keyboardState.IsKeyDown(Key.D))
            {
                pos = new Vector2(pos.X+1, pos.Y);
            }
            base.Update(DeltaTime, TotalTime);
        }

        public override void Draw(TimeSpan DeltaTime, TimeSpan TotalTime)
        {
            GraphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, new Color(100149237255), 1.0f0);

            _SpriteBatch.Begin(BlendState.AlphaBlend);
            _SpriteBatch.Draw(texture, pos, new Color(255255255255));
            _SpriteBatch.End();

            base.Draw(DeltaTime, TotalTime);
        }
    }
}

D键按下时,纹理会缓慢右移。当然,如果大家高兴的话,还可以自行实现W、A、S键的位移效果。

以上两节没有太多的难点,但却充当着重要的基础作用,建议大家自行理解并掌握。

 

以上,谢谢 ^ ^