Subscribe

RSS Feed (xml)

Powered By

Powered by Blogger

Google
 
xnahelp.blogspot.com

Jumat, 04 April 2008

Updating Our Input Handler

Before we actually dig into the code to utilize the XACT project we just created, let’s back
up a minute and take another look at our input handler. In particular we want to extend
our keyboard and gamepad functionality. Currently, if we try to trigger any event with a
key press or a button push we will get the event kicked off several times. This is because
for every frame we are checking in our Update method, if a key is pressed for a fraction of
a second the method will return true for many frames. We already know how to solve the
problem because we did it with our Mouse class. We stored the old state and compared it
to the new state to see what has changed. We need to do the same thing here. With the
mouse code, we did it inside of the demo code, but we want this to be done inside of the
library so our game and demo code do not need to worry about the gory details. We will
not be updating the mouse code but that would be an excellent exercise to go through
once we are done with the chapter.
To get started, we need to open up the InputHandler.cs code file inside of our XELibrary
project. The code for our updated InputHandler.cs file is in Listing 7.1. We are not going
to do a deep dive on the code in this chapter (this is devoted to sound after all), but we
are going to quickly examine what has been modified from a distant view.
LISTING 7.1 InputHandler.cs
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
namespace XELibrary
{
public interface IInputHandler
{
KeyboardHandler KeyboardState { get; }
GamePadState[] GamePads { get; }
ButtonHandler ButtonHandler { get; }
#if !XBOX360
MouseState MouseState { get; }
MouseState PreviousMouseState { get; }
134 CHAPTER 7 Sounds and Music
#endif
};
public partial class InputHandler
: Microsoft.Xna.Framework.GameComponent, IInputHandler
{
public enum ButtonType { A, B, Back, LeftShoulder, LeftStick,
RightShoulder, RightStick, Start, X, Y }
private KeyboardHandler keyboard;
private ButtonHandler gamePadHandler = new ButtonHandler();
private GamePadState[] gamePads = new GamePadState[4];
#if !XBOX360
private MouseState mouseState;
private MouseState prevMouseState;
#endif
public InputHandler(Game game)
: base(game)
{
// TODO: Construct any child components here
game.Services.AddService(typeof(IInputHandler), this);
//initialize our member fields
keyboard = new KeyboardHandler();
gamePads[0] = GamePad.GetState(PlayerIndex.One);
gamePads[1] = GamePad.GetState(PlayerIndex.Two);
gamePads[2] = GamePad.GetState(PlayerIndex.Three);
gamePads[3] = GamePad.GetState(PlayerIndex.Four);
#if !XBOX360
Game.IsMouseVisible = true;
prevMouseState = Mouse.GetState();
#endif
}
public override void Initialize()
{
base.Initialize();
}
public override void Update(GameTime gameTime)
{
Updating Our Input Handler 135
7
LISTING 7.1 Continued
keyboard.Update();
gamePadHandler.Update();
if (keyboard.IsKeyDown(Keys.Escape))
Game.Exit();
if (gamePadHandler.WasButtonPressed(0, ButtonType.Back))
Game.Exit();
#if !XBOX360
//Set our previous state
prevMouseState = mouseState;
//Get our new state
mouseState = Mouse.GetState();
#endif
base.Update(gameTime);
}
#region IInputHandler Members
public KeyboardHandler KeyboardState
{
get { return (keyboard); }
}
public ButtonHandler ButtonHandler
{
get { return (gamePadHandler); }
}
public GamePadState[] GamePads
{
get { return(gamePads); }
}
#if !XBOX360
public MouseState MouseState
{
get { return(mouseState); }
}
public MouseState PreviousMouseState
{
136 CHAPTER 7 Sounds and Music
LISTING 7.1 Continued
get { return(prevMouseState); }
}
#endif
#endregion
}
public class ButtonHandler
{
private GamePadState[] prevGamePadsState = new GamePadState[4];
private GamePadState[] gamePadsState = new GamePadState[4];
public ButtonHandler()
{
prevGamePadsState[0] = GamePad.GetState(PlayerIndex.One);
prevGamePadsState[1] = GamePad.GetState(PlayerIndex.Two);
prevGamePadsState[2] = GamePad.GetState(PlayerIndex.Three);
prevGamePadsState[3] = GamePad.GetState(PlayerIndex.Four);
}
public void Update()
{
//set our previous state to our new state
prevGamePadsState[0] = gamePadsState[0];
prevGamePadsState[1] = gamePadsState[1];
prevGamePadsState[2] = gamePadsState[2];
prevGamePadsState[3] = gamePadsState[3];
//get our new state
//gamePadsState = GamePad.State .GetState();
gamePadsState[0] = GamePad.GetState(PlayerIndex.One);
gamePadsState[1] = GamePad.GetState(PlayerIndex.Two);
gamePadsState[2] = GamePad.GetState(PlayerIndex.Three);
gamePadsState[3] = GamePad.GetState(PlayerIndex.Four);
}
public bool WasButtonPressed(int playerIndex,
InputHandler.ButtonType button)
{
int pi = playerIndex;
switch(button)
{ //start switch
case InputHandler.ButtonType.A:
{
return(gamePadsState[pi].Buttons.A == ButtonState.Pressed &&
Updating Our Input Handler 137
7
LISTING 7.1 Continued
prevGamePadsState[pi].Buttons.A == ButtonState.Released);
}
case InputHandler.ButtonType.B:
{
return(gamePadsState[pi].Buttons.B == ButtonState.Pressed &&
prevGamePadsState[pi].Buttons.B == ButtonState.Released);
}
case InputHandler.ButtonType.Back:
{
return(gamePadsState[pi].Buttons.Back == ButtonState.Pressed &&
prevGamePadsState[pi].Buttons.Back == ButtonState.Released);
}
case InputHandler.ButtonType.LeftShoulder:
{
return(gamePadsState[pi].Buttons.LeftShoulder ==
ButtonState.Pressed &&
prevGamePadsState[pi].Buttons.LeftShoulder ==
ButtonState.Released);
}
case InputHandler.ButtonType.LeftStick:
{
return(gamePadsState[pi].Buttons.LeftStick ==
ButtonState.Pressed &&
prevGamePadsState[pi].Buttons.LeftStick ==
ButtonState.Released);
}
case InputHandler.ButtonType.RightShoulder:
{
return(gamePadsState[pi].Buttons.RightShoulder ==
ButtonState.Pressed &&
prevGamePadsState[pi].Buttons.RightShoulder ==
ButtonState.Released);
}
case InputHandler.ButtonType.RightStick:
{
return(gamePadsState[pi].Buttons.RightStick ==
ButtonState.Pressed &&
prevGamePadsState[pi].Buttons.RightStick ==
ButtonState.Released);
}
case InputHandler.ButtonType.Start:
{
return(gamePadsState[pi].Buttons.Start ==
ButtonState.Pressed &&
138 CHAPTER 7 Sounds and Music
LISTING 7.1 Continued
prevGamePadsState[pi].Buttons.Start ==
ButtonState.Released);
}
case InputHandler.ButtonType.X:
{
return(gamePadsState[pi].Buttons.X == ButtonState.Pressed &&
prevGamePadsState[pi].Buttons.X == ButtonState.Released);
}
case InputHandler.ButtonType.Y:
{
return(gamePadsState[pi].Buttons.Y == ButtonState.Pressed &&
prevGamePadsState[pi].Buttons.Y == ButtonState.Released);
}
default:
throw (new ArgumentException());
} //end switch
}
}
public class KeyboardHandler
{
private KeyboardState prevKeyboardState;
private KeyboardState keyboardState;
public KeyboardHandler()
{
prevKeyboardState = Keyboard.GetState();
}
public bool IsKeyDown(Keys key)
{
return (keyboardState.IsKeyDown(key));
}
public bool IsHoldingKey(Keys key)
{
return(keyboardState.IsKeyDown(key) &&
prevKeyboardState.IsKeyDown(key));
}
public bool WasKeyPressed(Keys key)
{
return(keyboardState.IsKeyDown(key) &&
prevKeyboardState.IsKeyUp(key));
Updating Our Input Handler 139
7
LISTING 7.1 Continued
}
public bool HasReleasedKey(Keys key)
{
return(keyboardState.IsKeyUp(key) &&
prevKeyboardState.IsKeyDown(key));
}
public void Update()
{
//set our previous state to our new state
prevKeyboardState = keyboardState;
//get our new state
keyboardState = Keyboard.GetState();
}
}
}
The first thing to notice is that we added two more classes at the end of our file:
KeyboardHandler and ButtonHandler. These objects each have an Update method that
gets called by our main Update method inside of InputHandler. The Update method stores
the previous state and resets the new state. This is the key to it all. We simply check our
new state against our old state to see if keys or buttons have been pressed or released. We
have helper functions that our game code can call to check if the key was pressed or a
button was pressed. These helper functions just query the previous and new states of the
appropriate input device and return a boolean value. With this implemented we do not
run into the issue of getting multiple events kicked off because the gamer is holding the
button down. It also gives us a base from which to start working. We left our most current
state available, as we still need that for our triggers and Dpad. Dpad could also be put into
this handler because it is treated as a button, but that along with wrapping up the mouse
information is not in the code. This should be a good starting point if either of those is
needed, though.

0 komentar: