本稿では,OpenRCFでゲームパッドを使う方法を解説していきます.
OpenRCFは下記のサイトからダウンロードできます.
https://mase.openrcf.site/
ゲームパッドの入力方式
ゲームパッドには「X Input」と「Direct Input」の2つの方式があります.そして,本稿では「X Input」方式のゲームパッドを前提に説明を進めていきます.
Xbox360のコントローラは「X Input」で,プレイステーション5やNintendo Switchのコントローラは「Direct Input」と言われていますが,Amazonで売られている汎用ゲームパッドでは両者の切り替えができたりします.
Logicoolのゲームパッドでは,裏面に「X Input」と「Direct Input」を切り替えるボタンがありました.
SharpDX.XInputのインストール
Visual Studio の「ツール」→「NuGetパッケージマネージャー」→「ソリューションのNuGetパッケージの管理」を開きます.
参照に「SharpDX.XInput」と入力し,SharpDX.XInputをインストールします.
ソースコード
まず,MainWindow.xaml.csファイルの冒頭に「using SharpDX.XInput;」を追加します.次に「public partial class MainWindow : Window ~」の上に,以下のGamePadクラスをコピペします.ここではGamePadクラスを別ファイルに分割せずに,MainWindow.xaml.csファイルに書いてしまいます(ソースコードを綺麗に整理するという意味では,別ファイルに分割した方が良いです).
class GamePad
{
public bool A, B, X, Y, R, L;
public byte RT, LT;
public bool Up, Down, Left, Right;
public short LeftStickX, LeftStickY, RightStickX, RightStickY;
public bool LeftStickDown, RightStickDown;
private Controller controller = null;
private Gamepad pad;
public void Connect()
{
if (controller == null)
{
Controller[] controllers = new[] { new Controller(UserIndex.One), new Controller(UserIndex.Two), new Controller(UserIndex.Three), new Controller(UserIndex.Four) };
for (int i = 0; i < controllers.Length; i++)
{
if (controllers[i].IsConnected)
{
controller = controllers[i];
Console.WriteLine("GamePad is Connected.");
break;
}
}
}
}
public void GetState()
{
if (controller == null)
{
Console.WriteLine("Error : GamePad is not connected.");
}
else
{
try
{
pad = controller.GetState().Gamepad;
A = (pad.Buttons == GamepadButtonFlags.A);
B = (pad.Buttons == GamepadButtonFlags.B);
X = (pad.Buttons == GamepadButtonFlags.X);
Y = (pad.Buttons == GamepadButtonFlags.Y);
Up = (pad.Buttons == GamepadButtonFlags.DPadUp);
Down = (pad.Buttons == GamepadButtonFlags.DPadDown);
Left = (pad.Buttons == GamepadButtonFlags.DPadLeft);
Right = (pad.Buttons == GamepadButtonFlags.DPadRight);
R = (pad.Buttons == GamepadButtonFlags.RightShoulder);
L = (pad.Buttons == GamepadButtonFlags.LeftShoulder);
RT = pad.RightTrigger;
LT = pad.LeftTrigger;
LeftStickX = pad.LeftThumbX;
LeftStickY = pad.LeftThumbY;
LeftStickDown = (pad.Buttons == GamepadButtonFlags.LeftThumb);
RightStickX = pad.RightThumbX;
RightStickY = pad.RightThumbY;
RightStickDown = (pad.Buttons == GamepadButtonFlags.RightThumb);
}
catch
{
Console.WriteLine("Gamepad is disconnected.");
controller = null;
}
}
}
public void ConsoleWriteState()
{
Console.WriteLine("A:{0}, B:{1}, X:{2}, Y:{3}", A, B, X, Y);
Console.WriteLine("R:{0}, L:{1}, RT:{2}, LT:{3}", R, L, RT, LT);
Console.WriteLine("Up:{0}, Down:{1}, Left:{2}, Right:{3}", Up, Down, Left, Right);
Console.WriteLine("LeftStickX:{0}, LeftStickY:{1}, LeftStickDown:{2}", LeftStickX, LeftStickY, LeftStickDown);
Console.WriteLine("RightStickX:{0}, RightStickY:{1}, RightStickDown:{2}", RightStickX, RightStickY, RightStickDown);
}
}
public partial class MainWindow : Window
{
GamePad GamePad = new GamePad();
void Setup()
{
GamePad.Connect();
}
void Button1_Click(object sender, RoutedEventArgs e)
{
GamePad.GetState();
GamePad.ConsoleWriteState();
}
void GamePadKeyEvent()
{
GamePad.GetState();
if (GamePad.A)
{
Console.WriteLine("A");
}
else if (GamePad.B)
{
Console.WriteLine("B");
}
}
void Button2_Click(object sender, RoutedEventArgs e)
{
Parallel.RunEndless(GamePadKeyEvent, 50);
}
}
ここではSetup関数にGamePad.Connect()を記述したので,先にゲームパッドをPCに接続している必要があります.ボタン1を押すと各ボタン・ジョイスティックの状態が取得され,コンソールに表示されます.ボタン2を押すとGamePadKeyEvent()という関数が50ms周期で並列処理されるようになります.つまり,ボタン2を押してからは自動でゲームパッドの状態が取得され続けるようになり,if文の中身も実行されます.if文の条件分岐ではA,Bが押されているか否かしか反映させていませんが,他のボタンやジョイスティックの状態も取得できています.それらは以下の変数に格納されているので,必要に応じて活用してください.
public bool A, B, X, Y, R, L;
public byte RT, LT;
public bool Up, Down, Left, Right;
public short LeftStickX, LeftStickY, RightStickX, RightStickY;
public bool LeftStickDown, RightStickDown;
接続できない場合
上記のコードを実行してもゲームパッドに接続できなかった場合,そのゲームパッドは恐らく「Direct Input」方式です.対策としては,
- SharpDX.DirectInputというライブラリを使う.
- Amazonなどで「X Input」のゲームパッドを買う(2000円くらい).
- 「Direct Input」を「X Input」に変換するソフトを使う.
などが挙げられます.