12.4.1 创建InputHelper类

本节你将创建一些辅助类管理游戏输入,设置和生成随机数,这些类都在Helpers命名空间。

在“游戏玩法”一节中,我们注意到这个游戏可以使用键盘或手柄控制。XNA Framework 已经包含了管理键盘,手柄和鼠标(只在Windows平台支持)的所有类。但是因为你想同时处理键盘和鼠标,所以需要一个辅助类。而且,XNA输入类缺少某些功能,例如检查一个键是否是第一次被按下(释放后再次被按下),这个功能可以添加到InputHelper中。本节你将创建一个叫做InputHelper的处理输入的辅助类。

因为你可以使用手柄操作游戏,所以首先将游戏操作映射到手柄上,然后将手柄按钮映射到键盘上。例如,你可以将手柄的A键定义为跳,然后将键盘的空格键映射到手柄的A键。如果你首先将游戏动作映射到键盘,那么再将键盘映射到手柄是很困难的。

InputHelper类的属性和构造函数

InputHelper类存储了手柄、键盘的状态,并将手柄按键映射到键盘。InputHelper类还存储了当前玩家的索引,这是因为每个InputHelper类的实例只能处理一个玩家的输入。所以,如果有两个玩家,需要有两个InputHelper对象。

因为你需要检查按钮或键是否是第一次被按下,所以要存储手柄和键盘的当前状态和上一次的状态,下列代码是InputHelper类的属性和构造函数:

PlayerIndex playerIndex; 
// Keyboard 
KeyboardState keyboardState; 
KeyboardState lastKeyboardState; 
Dictionary<Buttons, Keys> keyboardMap; 

// Gamepad 
GamePadState gamePadState; 
GamePadState lastGamePadState; 

public InputHelper(PlayerIndex playerIndex): this(playerIndex, null) { } 

public InputHelper(PlayerIndex playerIndex, Dictionary<Buttons, Keys> keyboardMap)
{
    this.playerIndex = playerIndex; 
    this.keyboardMap = keyboardMap; 
} 

InputHelper的构造函数的参数是玩家索引和键盘映射。但是,如果你不想使用键盘可以讲键盘映射的参数设置为null。

更新输入

要更新输入,你需要保存键盘和手柄的上次状态和读取新的状态。注意在XNA 2.0中,Keyboard类的GetState方法接受当前玩家的索引。下面的代码是InputHelper类的Update方法。

public void Update() 
{
    lastKeyboardState = keyboardState; 
    keyboardState = Keyboard.GetState(playerIndex); 
    lastGamePadState = gamePadState; 
    gamePadState = GamePad.GetState(playerIndex); 
} 

检测按下的键

在XNA 2.0中,KeyboardState和GamePadState都有一个方法检查一个按键或键是否被按下。因为你通过键盘或手柄处理输入,所以需要检查一个按钮或键是否被按下,但应避免同时检查两者。

InputHelper类只检查手柄是否被按下,但内部检查手柄或键盘是否被按下。这里,首先检查手柄是否被连接,如果是则检查按钮是否被按下。否则,如果InputHelper类有正确的键盘映射,它将检查映射到手柄按钮的键盘键是否被按下。下面的代码是InputHelper类的IsKeyPressed方法:

public bool IsKeyPressed(Buttons button) 
{
    bool pressed = false; 
    if (gamePadState.IsConnected) 
        pressed = gamePadState.IsButtonDown(button); 
    else if (keyboardMap != null) 
    {
        Keys key = keyboardMap[button]; 
        pressed = keyboardState.IsKeyDown(key); 
    }
    return pressed; 
} 

除了检查按钮是否被按下,你还要检查按钮是否是第一次被按下。要做到这点,你可以检查按下的按钮在前一次更新中是否已被释放。下面的代码是InputHelper类中的IsKeyJustPressed方法:

public bool IsKeyJustPressed(Buttons button)
{
    bool pressed = false; 
    if(gamePadState.IsConnected) 
        pressed = (gamePadState.IsButtonDown(button) && lastGamePadState.IsButtonUp(button)); 
    else if (keyboardMap != null) 
    {
        Keys key = keyboardMap[button]; 
        pressed = (keyboardState.IsKeyDown(key) &&lastKeyboardState.IsKeyUp(key)); 
    }
    return pressed; 
}

检测类比键的状态

你可以使用IsKeyPressed和IsKeyJustPressed方法检查一个数字键是否被按下,但如果你用同样的方法检查Xbox360手柄的类比摇杆或扳机,只能获得一个Boolean值,表示是否被按下。

在XNA的GamePadState类中,每个类比摇杆的位置是一个Vector2对象,扳机状态是一个浮点值。在InputHelper类中,你将使用和GamePadState类中相同的方法处理手柄类比摇杆。注意你还需要正确处理映射到摇杆的键盘。下面是InputHelper类的GetLeftThumbStick方法的代码:

public Vector2 GetLeftThumbStick() 
{
    Vector2 thumbPosition = Vector2.Zero; 
    if (gamePadState.IsConnected) 
        thumbPosition = gamePadState.ThumbSticks.Left; 
    else if (keyboardMap != null) 
    {
        if (keyboardState.IsKeyDown( keyboardMap[Buttons.LeftThumbstickUp])) 
            thumbPosition.Y = 1; 
        else if (keyboardState.IsKeyDown(keyboardMap[Buttons.LeftThumbstickDown])) 
            thumbPosition.Y = -1; 
        if (keyboardState.IsKeyDown( keyboardMap[Buttons.LeftThumbstickRight])) 
            thumbPosition.X = 1; 
        else if (keyboardState.IsKeyDown(keyboardMap[Buttons.LeftThumbstickLeft])) 
            thumbPosition.X = -1; 
     }
     return thumbPosition; 
 } 

在GetLeftThumbStick方法中使用与IsKeyPressed方法同样的思路:首先检查手柄是否已连接,如果是,只需返回期望的值。否则,检测映射到左摇杆的键盘的状态(上、下、左、右)并返回一个包含摇杆位置的Vector2值。除了GetLeftThumbStick方法,你还要创建GetRightThumbStick方法处理手柄右摇杆的位置。下面是GetRightThumbStick方法的代码:

public Vector2 GetRightThumbStick()
{
    Vector2 thumbPosition = Vector2.Zero; 
    if (gamePadState.IsConnected) 
        thumbPosition = gamePadState.ThumbSticks.Right; 
    else if (keyboardMap != null) 
    {
        if (keyboardState.IsKeyDown( keyboardMap[Buttons.RightThumbstickUp])) 
            thumbPosition.Y = 1; 
        else if (keyboardState.IsKeyDown(keyboardMap[Buttons.RightThumbstickDown])) 
            thumbPosition.Y = -1; 
        if (keyboardState.IsKeyDown(keyboardMap[Buttons.RightThumbstickRight])) 
            thumbPosition.X = 1; 
        else if (keyboardState.IsKeyDown(keyboardMap[Buttons.RightThumbstickLeft])) 
            thumbPosition.X = -1; 
    }
    return thumbPosition; 
} 

发布时间:2009/5/27 下午2:22:16  阅读次数:4671

2006 - 2024,推荐分辨率 1024*768 以上,推荐浏览器 Chrome、Edge 等现代浏览器,截止 2021 年 12 月 5 日的访问次数:1872 万 9823 站长邮箱

沪 ICP 备 18037240 号-1

沪公网安备 31011002002865 号