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 阅读次数:5165