Add gamepad support

This commit is contained in:
Drew DeVault 2015-10-01 08:46:09 -04:00
parent 394bb0953a
commit 578c5af3b9
9 changed files with 257 additions and 42 deletions

View File

@ -0,0 +1,10 @@
using System;
using Microsoft.Xna.Framework.Input;
namespace TrueCraft.Client.Input
{
public class GamePadButtonEventArgs : GamePadEventArgs
{
public Buttons Button { get; set; }
}
}

View File

@ -0,0 +1,8 @@
using System;
namespace TrueCraft.Client.Input
{
public class GamePadEventArgs : EventArgs
{
}
}

View File

@ -0,0 +1,67 @@
using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using System.Linq;
namespace TrueCraft.Client.Input
{
public class GamePadHandler : GameComponent
{
public GamePadState State { get; set; }
public PlayerIndex PlayerIndex { get; set; }
public event EventHandler<GamePadButtonEventArgs> ButtonDown;
public event EventHandler<GamePadButtonEventArgs> ButtonUp;
public GamePadHandler(Game game) : base(game)
{
PlayerIndex = PlayerIndex.One;
}
public override void Initialize()
{
State = GamePad.GetState(PlayerIndex);
base.Initialize();
}
public override void Update(GameTime gameTime)
{
var newState = GamePad.GetState(PlayerIndex);
Process(newState, State);
State = newState;
base.Update(gameTime);
}
private void Process(GamePadState newState, GamePadState oldState)
{
if (!newState.IsConnected)
return;
if (newState.Buttons != oldState.Buttons)
{
var newButtons = Enum.GetValues(typeof(Buttons))
.Cast<Buttons>()
.Where(newState.IsButtonDown);
var oldButtons = Enum.GetValues(typeof(Buttons))
.Cast<Buttons>()
.Where(oldState.IsButtonDown);
var pressed = newButtons.Except(oldButtons).ToArray();
var unpressed = oldButtons.Except(newButtons).ToArray();
foreach (var button in pressed)
{
if (ButtonDown != null)
ButtonDown(this, new GamePadButtonEventArgs { Button = button });
}
foreach (var button in unpressed)
{
if (ButtonUp != null)
ButtonUp(this, new GamePadButtonEventArgs { Button = button });
}
}
}
}
}

View File

@ -9,7 +9,7 @@ using System.Text;
namespace TrueCraft.Client.Modules
{
public class DebugInfoModule : IGraphicalModule, IInputModule
public class DebugInfoModule : InputModule, IGraphicalModule
{
public bool Chunks { get; set; }
@ -28,7 +28,7 @@ namespace TrueCraft.Client.Modules
#endif
}
public bool KeyDown(GameTime gameTime, KeyboardKeyEventArgs e)
public override bool KeyDown(GameTime gameTime, KeyboardKeyEventArgs e)
{
switch (e.Key)
{
@ -38,7 +38,7 @@ namespace TrueCraft.Client.Modules
return false;
}
public bool KeyUp(GameTime gameTime, KeyboardKeyEventArgs e)
public override bool KeyUp(GameTime gameTime, KeyboardKeyEventArgs e)
{
switch (e.Key)
{
@ -49,30 +49,6 @@ namespace TrueCraft.Client.Modules
return false;
}
public bool MouseScroll(GameTime gameTime, MouseScrollEventArgs e)
{
return false;
}
public bool MouseMove(GameTime gameTime, MouseMoveEventArgs e)
{
return false;
}
public bool MouseButtonDown(GameTime gameTime, MouseButtonEventArgs e)
{
return false;
}
public bool MouseButtonUp(GameTime gameTime, MouseButtonEventArgs e)
{
return false;
}
public void Update(GameTime gameTime)
{
}
public void Draw(GameTime gameTime)
{
if (!Enabled)

View File

@ -11,5 +11,7 @@ namespace TrueCraft.Client.Modules
bool MouseButtonDown(GameTime gameTime, MouseButtonEventArgs e);
bool MouseButtonUp(GameTime gameTime, MouseButtonEventArgs e);
bool MouseScroll(GameTime gameTime, MouseScrollEventArgs e);
bool GamePadButtonDown(GameTime gameTime, GamePadButtonEventArgs e);
bool GamePadButtonUp(GameTime gameTime, GamePadButtonEventArgs e);
}
}

View File

@ -0,0 +1,53 @@
using System;
using TrueCraft.Client.Input;
using Microsoft.Xna.Framework;
namespace TrueCraft.Client.Modules
{
public abstract class InputModule : IInputModule
{
public virtual bool KeyDown(GameTime gameTime, KeyboardKeyEventArgs e)
{
return false;
}
public virtual bool KeyUp(GameTime gameTime, KeyboardKeyEventArgs e)
{
return false;
}
public virtual bool MouseMove(GameTime gameTime, MouseMoveEventArgs e)
{
return false;
}
public virtual bool MouseButtonDown(GameTime gameTime, MouseButtonEventArgs e)
{
return false;
}
public virtual bool MouseButtonUp(GameTime gameTime, MouseButtonEventArgs e)
{
return false;
}
public virtual bool MouseScroll(GameTime gameTime, MouseScrollEventArgs e)
{
return false;
}
public virtual bool GamePadButtonDown(GameTime gameTime, GamePadButtonEventArgs e)
{
return false;
}
public virtual bool GamePadButtonUp(GameTime gameTime, GamePadButtonEventArgs e)
{
return false;
}
public virtual void Update(GameTime gameTime)
{
}
}
}

View File

@ -11,13 +11,14 @@ using TrueCraft.Core.Networking.Packets;
namespace TrueCraft.Client.Modules
{
public class PlayerControlModule : IInputModule
public class PlayerControlModule : InputModule
{
private TrueCraftGame Game { get; set; }
private DateTime NextAnimation { get; set; }
private XVector3 Delta { get; set; }
private bool Capture { get; set; }
private bool Digging { get; set; }
private GamePadState GamePadState { get; set; }
public PlayerControlModule(TrueCraftGame game)
{
@ -28,9 +29,10 @@ namespace TrueCraft.Client.Modules
Game.EndDigging = DateTime.MaxValue;
Game.TargetBlock = -Coordinates3D.One;
NextAnimation = DateTime.MaxValue;
GamePadState = GamePad.GetState(PlayerIndex.One);
}
public bool KeyDown(GameTime gameTime, KeyboardKeyEventArgs e)
public override bool KeyDown(GameTime gameTime, KeyboardKeyEventArgs e)
{
switch (e.Key)
{
@ -129,7 +131,7 @@ namespace TrueCraft.Client.Modules
return false;
}
public bool KeyUp(GameTime gameTime, KeyboardKeyEventArgs e)
public override bool KeyUp(GameTime gameTime, KeyboardKeyEventArgs e)
{
switch (e.Key)
{
@ -160,7 +162,36 @@ namespace TrueCraft.Client.Modules
return false;
}
public bool MouseScroll(GameTime gameTime, MouseScrollEventArgs e)
public override bool GamePadButtonDown(GameTime gameTime, GamePadButtonEventArgs e)
{
var selected = Game.Client.HotbarSelection;
switch (e.Button)
{
case Buttons.LeftShoulder:
selected--;
if (selected < 0)
selected = 8;
if (selected > 8)
selected = 0;
Game.Client.HotbarSelection = selected;
break;
case Buttons.RightShoulder:
selected++;
if (selected < 0)
selected = 8;
if (selected > 8)
selected = 0;
Game.Client.HotbarSelection = selected;
break;
case Buttons.A:
if (Math.Floor(Game.Client.Position.Y) == Game.Client.Position.Y)
Game.Client.Velocity += TrueCraft.API.Vector3.Up * 0.3;
break;
}
return false;
}
public override bool MouseScroll(GameTime gameTime, MouseScrollEventArgs e)
{
var selected = Game.Client.HotbarSelection;
selected += e.DeltaValue > 0 ? -1 : 1;
@ -172,7 +203,7 @@ namespace TrueCraft.Client.Modules
return true;
}
public bool MouseMove(GameTime gameTime, MouseMoveEventArgs e)
public override bool MouseMove(GameTime gameTime, MouseMoveEventArgs e)
{
if (!Capture)
return false;
@ -191,7 +222,7 @@ namespace TrueCraft.Client.Modules
return true;
}
public bool MouseButtonDown(GameTime gameTime, MouseButtonEventArgs e)
public override bool MouseButtonDown(GameTime gameTime, MouseButtonEventArgs e)
{
switch (e.Button)
{
@ -224,23 +255,47 @@ namespace TrueCraft.Client.Modules
NextAnimation = DateTime.UtcNow.AddSeconds(0.25);
}
public bool MouseButtonUp(GameTime gameTime, MouseButtonEventArgs e)
public override bool MouseButtonUp(GameTime gameTime, MouseButtonEventArgs e)
{
switch (e.Button)
{
case MouseButton.Left:
Digging = false;
Game.StartDigging = DateTime.MinValue;
Game.EndDigging = DateTime.MaxValue;
Game.TargetBlock = -Coordinates3D.One;
return true;
}
return false;
}
public void Update(GameTime gameTime)
public override void Update(GameTime gameTime)
{
if (Digging)
var delta = Delta;
var gamePad = GamePad.GetState(PlayerIndex.One); // TODO: Can this stuff be done effectively in the GamePadHandler?
if (gamePad.IsConnected && gamePad.ThumbSticks.Left.Length() != 0)
delta = new XVector3(gamePad.ThumbSticks.Left.X, 0, gamePad.ThumbSticks.Left.Y);
var digging = Digging;
if (gamePad.IsConnected && gamePad.Triggers.Right > 0.5f)
digging = true;
if (gamePad.IsConnected && gamePad.Triggers.Left > 0.5f && GamePadState.Triggers.Left < 0.5f)
{
var item = Game.Client.Inventory.Hotbar[Game.Client.HotbarSelection];
Game.Client.QueuePacket(new PlayerBlockPlacementPacket(
Game.HighlightedBlock.X, (sbyte)Game.HighlightedBlock.Y, Game.HighlightedBlock.Z,
Game.HighlightedBlockFace, item.ID, item.Count, item.Metadata));
}
if (gamePad.IsConnected && gamePad.ThumbSticks.Right.Length() != 0)
{
var look = -(gamePad.ThumbSticks.Right * 8) * (float)(gameTime.ElapsedGameTime.TotalSeconds * 30);
Game.Client.Yaw -= look.X;
Game.Client.Pitch -= look.Y;
Game.Client.Yaw %= 360;
Game.Client.Pitch = MathHelper.Clamp(Game.Client.Pitch, -89.9f, 89.9f);
}
if (digging)
{
if (Game.StartDigging == DateTime.MinValue) // Would like to start digging a block
{
@ -261,10 +316,16 @@ namespace TrueCraft.Client.Modules
BeginDigging(target);
}
}
if (Delta != XVector3.Zero)
else
{
var lookAt = XVector3.Transform(-Delta,
Game.StartDigging = DateTime.MinValue;
Game.EndDigging = DateTime.MaxValue;
Game.TargetBlock = -Coordinates3D.One;
}
if (delta != XVector3.Zero)
{
var lookAt = XVector3.Transform(-delta,
Matrix.CreateRotationY(MathHelper.ToRadians(-(Game.Client.Yaw - 180) + 180)));
lookAt.X *= (float)(gameTime.ElapsedGameTime.TotalSeconds * 4.3717);
@ -293,6 +354,8 @@ namespace TrueCraft.Client.Modules
Game.EndDigging = DateTime.MaxValue;
}
}
GamePadState = gamePad;
}
}
}

View File

@ -137,6 +137,10 @@
<Compile Include="Handlers\InventoryHandlers.cs" />
<Compile Include="Handlers\ChunkHandlers.cs" />
<Compile Include="Rendering\IconRenderer.cs" />
<Compile Include="Modules\InputModule.cs" />
<Compile Include="Input\GamePadHandler.cs" />
<Compile Include="Input\GamePadEventArgs.cs" />
<Compile Include="Input\GamePadButtonEventArgs.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>

View File

@ -43,6 +43,7 @@ namespace TrueCraft.Client
private SpriteBatch SpriteBatch { get; set; }
private KeyboardHandler KeyboardComponent { get; set; }
private MouseHandler MouseComponent { get; set; }
private GamePadHandler GamePadComponent { get; set; }
private RenderTarget2D RenderTarget { get; set; }
private int ThreadID { get; set; }
@ -90,6 +91,9 @@ namespace TrueCraft.Client
MouseComponent = new MouseHandler(this);
Components.Add(MouseComponent);
GamePadComponent = new GamePadHandler(this);
Components.Add(GamePadComponent);
}
void Window_ClientSizeChanged(object sender, EventArgs e)
@ -144,6 +148,8 @@ namespace TrueCraft.Client
MouseComponent.ButtonUp += OnMouseComponentButtonUp;
KeyboardComponent.KeyDown += OnKeyboardKeyDown;
KeyboardComponent.KeyUp += OnKeyboardKeyUp;
GamePadComponent.ButtonDown += OnGamePadButtonDown;
GamePadComponent.ButtonUp += OnGamePadButtonUp;
CreateRenderTarget();
SpriteBatch = new SpriteBatch(GraphicsDevice);
@ -218,6 +224,32 @@ namespace TrueCraft.Client
}
}
private void OnGamePadButtonUp(object sender, GamePadButtonEventArgs e)
{
foreach (var module in Modules)
{
var input = module as IInputModule;
if (input != null)
{
if (input.GamePadButtonUp(GameTime, e))
break;
}
}
}
private void OnGamePadButtonDown(object sender, GamePadButtonEventArgs e)
{
foreach (var module in Modules)
{
var input = module as IInputModule;
if (input != null)
{
if (input.GamePadButtonDown(GameTime, e))
break;
}
}
}
private void OnMouseComponentScroll(object sender, MouseScrollEventArgs e)
{
foreach (var module in Modules)