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