Add Input class to group gamepad & keyboard inputs together.

For motion directions (up/down & left/right), have them cancel each other out
if the player attempts to go in opposite directions at once.

Refactor Player & SneakGame to use the new Input class & remove direct access
to Keyboard & GamePad.

GitOrigin-RevId: 80fbed887408ae2b80c01273a49b150f38285dcb
This commit is contained in:
Colin McMillen 2020-01-16 17:02:38 -05:00
parent 9a1c6646dd
commit db6f3e1425
4 changed files with 67 additions and 30 deletions

51
Shared/Input.cs Normal file
View File

@ -0,0 +1,51 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
namespace SemiColinGames {
struct Input {
public bool Jump;
public bool Attack;
public Vector2 Motion;
public bool Exit;
public bool FullScreen;
public bool Debug;
public Input(GamePadState gamePad, KeyboardState keyboard) {
// First we process normal buttons.
Jump = gamePad.IsButtonDown(Buttons.A) || keyboard.IsKeyDown(Keys.J);
Attack = gamePad.IsButtonDown(Buttons.X) || keyboard.IsKeyDown(Keys.K);
// Then special debugging sorts of buttons.
Exit = gamePad.IsButtonDown(Buttons.Start) || keyboard.IsKeyDown(Keys.Escape);
FullScreen = gamePad.IsButtonDown(Buttons.Back) || keyboard.IsKeyDown(Keys.F12) ||
keyboard.IsKeyDown(Keys.OemPlus);
Debug = gamePad.IsButtonDown(Buttons.LeftShoulder) || keyboard.IsKeyDown(Keys.OemMinus);
// Then potential motion directions. If the player attempts to input opposite directions at
// once (up & down or left & right), those inputs cancel out, resulting in no motion.
Motion = new Vector2();
Vector2 leftStick = gamePad.ThumbSticks.Left;
bool left = leftStick.X < -0.5 || gamePad.IsButtonDown(Buttons.DPadLeft) ||
keyboard.IsKeyDown(Keys.A);
bool right = leftStick.X > 0.5 || gamePad.IsButtonDown(Buttons.DPadRight) ||
keyboard.IsKeyDown(Keys.D);
bool up = leftStick.Y > 0.5 || gamePad.IsButtonDown(Buttons.DPadUp) ||
keyboard.IsKeyDown(Keys.W);
bool down = leftStick.Y < -0.5 || gamePad.IsButtonDown(Buttons.DPadDown) ||
keyboard.IsKeyDown(Keys.S);
if (left && !right) {
Motion.X = -1;
}
if (right && !left) {
Motion.X = 1;
}
if (up && !down) {
Motion.Y = 1;
}
if (down && !up) {
Motion.Y = -1;
}
}
}
}

View File

@ -35,12 +35,10 @@ namespace SemiColinGames {
return new Rectangle(position.X - spriteWidth, position.Y - 7, spriteWidth * 2, 26); return new Rectangle(position.X - spriteWidth, position.Y - 7, spriteWidth * 2, 26);
} }
public void Update( public void Update(GameTime time, History<Input> input, List<Rectangle> collisionTargets) {
GameTime time, History<GamePadState> gamePad, History<KeyboardState> keyboard,
List<Rectangle> collisionTargets) {
Point oldPosition = position; Point oldPosition = position;
AirState oldAirState = airState; AirState oldAirState = airState;
UpdateFromInput(time, gamePad, keyboard); HandleInput(time, input);
Rectangle oldBbox = Bbox(oldPosition); Rectangle oldBbox = Bbox(oldPosition);
Rectangle playerBbox = Bbox(position); Rectangle playerBbox = Bbox(position);
@ -97,11 +95,8 @@ namespace SemiColinGames {
} }
} }
void UpdateFromInput( void HandleInput(GameTime time, History<Input> input) {
GameTime time, History<GamePadState> gamePad, History<KeyboardState> keyboard) { if (input[0].Jump && !input[1].Jump && airState == AirState.Ground) {
if ((gamePad[0].IsButtonDown(Buttons.A) && gamePad[1].IsButtonUp(Buttons.A) ||
keyboard[0].IsKeyDown(Keys.J) && keyboard[1].IsKeyUp(Keys.J)) &&
airState == AirState.Ground) {
pose = Pose.Jumping; pose = Pose.Jumping;
airState = AirState.Jumping; airState = AirState.Jumping;
jumpTime = 0.5; jumpTime = 0.5;
@ -109,30 +104,23 @@ namespace SemiColinGames {
return; return;
} }
if ((gamePad[0].IsButtonDown(Buttons.X) && gamePad[1].IsButtonUp(Buttons.X) || if (input[0].Attack && !input[1].Attack && swordSwingTime <= 0) {
keyboard[0].IsKeyDown(Keys.K) && keyboard[1].IsKeyUp(Keys.K))
&& swordSwingTime <= 0) {
pose = Pose.SwordSwing; pose = Pose.SwordSwing;
swordSwingTime = 0.3; swordSwingTime = 0.3;
return; return;
} }
Vector2 leftStick = gamePad[0].ThumbSticks.Left; if (input[0].Motion.X < 0) {
if (gamePad[0].IsButtonDown(Buttons.DPadLeft) || leftStick.X < -0.5 ||
keyboard[0].IsKeyDown(Keys.A)) {
facing = Facing.Left; facing = Facing.Left;
pose = Pose.Walking; pose = Pose.Walking;
position.X -= (int) (moveSpeed * time.ElapsedGameTime.TotalSeconds); position.X -= (int) (moveSpeed * time.ElapsedGameTime.TotalSeconds);
} else if (gamePad[0].IsButtonDown(Buttons.DPadRight) || leftStick.X > 0.5 || } else if (input[0].Motion.X > 0) {
keyboard[0].IsKeyDown(Keys.D)) {
facing = Facing.Right; facing = Facing.Right;
pose = Pose.Walking; pose = Pose.Walking;
position.X += (int) (moveSpeed * time.ElapsedGameTime.TotalSeconds); position.X += (int) (moveSpeed * time.ElapsedGameTime.TotalSeconds);
} else if (gamePad[0].IsButtonDown(Buttons.DPadDown) || leftStick.Y < -0.5 || } else if (input[0].Motion.Y < 0) {
keyboard[0].IsKeyDown(Keys.S)) {
pose = Pose.Crouching; pose = Pose.Crouching;
} else if (gamePad[0].IsButtonDown(Buttons.DPadUp) || leftStick.Y > 0.5 || } else if (input[0].Motion.Y > 0) {
keyboard[0].IsKeyDown(Keys.W)) {
pose = Pose.Stretching; pose = Pose.Stretching;
} else { } else {
pose = Pose.Standing; pose = Pose.Standing;

View File

@ -10,6 +10,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)Camera.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Camera.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Input.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Debug.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Debug.cs" />
<Compile Include="$(MSBuildThisFileDirectory)FpsCounter.cs" /> <Compile Include="$(MSBuildThisFileDirectory)FpsCounter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)History.cs" /> <Compile Include="$(MSBuildThisFileDirectory)History.cs" />

View File

@ -17,6 +17,7 @@ namespace SemiColinGames {
History<KeyboardState> keyboard = new History<KeyboardState>(2); History<KeyboardState> keyboard = new History<KeyboardState>(2);
History<GamePadState> gamePad = new History<GamePadState>(2); History<GamePadState> gamePad = new History<GamePadState>(2);
History<Input> input = new History<Input>(2);
FpsCounter fpsCounter = new FpsCounter(); FpsCounter fpsCounter = new FpsCounter();
Texture2D grasslandBg1; Texture2D grasslandBg1;
@ -66,27 +67,23 @@ namespace SemiColinGames {
protected override void Update(GameTime gameTime) { protected override void Update(GameTime gameTime) {
Debug.Clear(); Debug.Clear();
gamePad.Add(GamePad.GetState(PlayerIndex.One)); input.Add(new Input(GamePad.GetState(PlayerIndex.One), Keyboard.GetState()));
keyboard.Add(Keyboard.GetState());
if (keyboard[0].IsKeyDown(Keys.Escape) || gamePad[0].IsButtonDown(Buttons.Start)) { if (input[0].Exit) {
Exit(); Exit();
} }
if (keyboard[0].IsKeyDown(Keys.F12) && keyboard[1].IsKeyUp(Keys.F12) || if (input[0].FullScreen && !input[1].FullScreen) {
keyboard[0].IsKeyDown(Keys.OemPlus) && keyboard[1].IsKeyUp(Keys.OemPlus) ||
gamePad[0].IsButtonDown(Buttons.Back) && gamePad[1].IsButtonUp(Buttons.Back)) {
fullScreen = !fullScreen; fullScreen = !fullScreen;
display.SetFullScreen(fullScreen); display.SetFullScreen(fullScreen);
} }
if (gamePad[0].IsButtonDown(Buttons.LeftShoulder) && gamePad[1].IsButtonUp(Buttons.LeftShoulder) || if (input[0].Debug && !input[1].Debug) {
keyboard[0].IsKeyDown(Keys.OemMinus) && keyboard[1].IsKeyUp(Keys.OemMinus)) {
Debug.Enabled = !Debug.Enabled; Debug.Enabled = !Debug.Enabled;
} }
List<Rectangle> collisionTargets = world.CollisionTargets(); List<Rectangle> collisionTargets = world.CollisionTargets();
player.Update(gameTime, gamePad, keyboard, collisionTargets); player.Update(gameTime, input, collisionTargets);
camera.Update(gameTime, player.Position); camera.Update(gameTime, player.Position);