DirectInputでゲームパッドやジョイスティックの入力を取る時に、ボタンがZ軸に割り当てられていると同時押しが検知できない場合があります。その問題の対処法。
これは主にZLやZRのトリガー系のボタンで起こる問題です。ボタンでありながら押し込みの感度が取れるというメリットがあるのですが、同時入力には対応していません。
なのでDirectInput以外の方法で入力を取る必要があります。
ZLとZRだとこんな感じになります。
ZLとZR同時押しのときは無入力状態と同じです(値は128)
これでは困ることがあるのでなんとかしましょう。
XInputで受け取るようにしよう!
C#でDirectInputを扱っていたということでSlimDXを使っていること前提で書きます。
ということでSlimDXのXInputの使い方を紹介するだけの内容になります。
MainWindow.xaml
<Grid>
<Button Content="Button" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
</Grid>
MainWindow.xaml.cs
/// <summary>
/// 入力監視タスクの起動
/// </summary>
private void GetInputTask()
{
//タイマーの間隔(ミリ秒)
System.Timers.Timer timer = new System.Timers.Timer(16);
//タイマーの処理
timer.Elapsed += (sender, e) =>
{
//GetGamepadInput();
UpdateJoyStickInfo_Xinput();
//切断ボタンが押されたら停止
if (!taskState)
{
timer.Stop();
timer = null;
}
};
//タイマーを開始する
timer.Start();
}
/// <summary>
/// 入力を取得、表示
/// </summary>
private void GetGamepadInput()
{
//1つ目のデバイスを指定
SlimDX.XInput.Controller controller = new SlimDX.XInput.Controller(SlimDX.XInput.UserIndex.One);
//入力状態を取得
State state = controller.GetState();
Console.WriteLine("buttons:" + state.Gamepad.Buttons + " LT:" + state.Gamepad.LeftTrigger + " RT:" + state.Gamepad.RightTrigger);
}
// タスク制御用
public bool taskState = false;
/// <summary>
/// タスクの起動、終了ボタン
/// </summary>
private void Button_Click(object sender, RoutedEventArgs e)
{
if (!taskState)
{
GetInputTask();
taskState = true;
}
else
{
taskState = false;
}
}
使い方はDirectInputと同じく簡単です。
入力を取りたいコントローラーを指定しておいてGetState()で入力状態を取ります。
DirectInputと同じように入力状態を監視用の処理を回しておきましょう。今回はタスクを使っています。
入力状態が入ったstateから細かくボタンを取り出すには
- state.Gamepad.Buttons
- state.Gamepad.LeftTrigger
- state.Gamepad.RightTrigger
などがあります。今回はZLZRを含めたボタン群だけ表示するようにしています。
Buttonsでは使い勝手が悪いと思うのでHasFlag()というメソッドで個々の入力をboolで受け取ることもできます。
Aボタンを確認する例:
state.Gamepad.Buttons.HasFlag(SlimDX.XInput.GamepadButtonFlags.A);
詳しくはドキュメントに載っています。
SlimDX.XInput Namespace
https://slimdx.org/docs/html/N_SlimDX_XInput.htm
DirectInputからXinputへ移行するのは面倒だと思いますがトリガーの同時押しが検出できないとなれば問題になってくる場合もあるので頑張るしかないですね。
DirectInputと共存可能なのでトリガー部分だけXInputで取るというのも良いと思います。