Pongeponge

ゲームコンローラーの情報取得

Wii Super Famicom Classic Controller
Wii Super Famicom Classic Controller / id:takefumi

 C#ゲームコントローラーの情報をどうやって取得するのか疑問に思ったので調べてみた。

C# での ゲームパッドの使用 • C言語交流フォーラム ~ mixC++ ~
 どうやらSlimDXが使えそう。

SlimDX Homepage
SlimDXはじめてみる - 三次元日誌
 SlimDXをインストールして、参照の追加。
するとここでエラーが出る。

警告 1 構築されているプロジェクトのプロセッサ アーキテクチャ "MSIL" と、参照 "SlimDX, Version=4.0.13.43, Culture=neutral, PublicKeyToken=b1b0c32fd1ffe4f9, processorArchitecture=AMD64" のプロセッサ アーキテクチャ "AMD64" の間には不一致がありました。この不一致は、ランタイム エラーを発生させる可能性があります。プロジェクトと参照の間でプロセッサ アーキテクチャが一致するように、構成マネージャーを使用してターゲットとするプロジェクトのプロセッサ アーキテクチャを変更するか、ターゲットとするプロジェクトのプロセッサ アーキテクチャに一致するプロジェクト アーキテクチャとの依存関係を参照で設定することを検討してください。

 よくわからない。
構成マネージャー見てみたけど、CPUはAny CPU,x64,x86しかなかった。
x86にすれば警告は消えるんだろうか?
とりあえず放置してても動くので放置。

Reading one Joystick (PS1/PS2) using slimDX and C# [Archive] - Chief Delphi
 コントローラーの情報を取得するソースコードは、ほぼこれをコピペ。

 とりあえずWPFウィンドウにボタン2つとテキストブロック貼り付けたはいいけど、
更新に使おうと思ってたタイマーが見当たらない…。

[XAML/C#] WPF でタイマーを使うには (Windows フォームから WPF へ)
 どうやらWPFにタイマーはなくて、代わりにDispatcherTimerを使えと。

結果、こんな感じに。

MainWindow.xaml

<Window x:Class="WpfJoypad.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Button x:Name="Start_Button" Content="Start" HorizontalAlignment="Left" Margin="10,290,0,0" VerticalAlignment="Top" Width="75" Click="Start_Button_Click"/>
        <Button x:Name="Stop_Button" Content="Stop" HorizontalAlignment="Left" Margin="90,290,0,0" VerticalAlignment="Top" Width="75" Click="Stop_Button_Click"/>
        <TextBlock x:Name="data_TextBlock" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top"/>

    </Grid>
</Window>

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;

namespace WpfJoypad
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window
    {
        private DispatcherTimer timer;
        private JoypadInfomation joypad;

        public MainWindow()
        {
            InitializeComponent();
            this.TimerSettings();
            this.joypad = new JoypadInfomation();

        }

        /// <summary>
        /// スタートボタン
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Start_Button_Click(object sender, RoutedEventArgs e)
        {
            this.timer.Start();
        }

        /// <summary>
        /// ストップボタン
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Stop_Button_Click(object sender, RoutedEventArgs e)
        {
            this.timer.Stop();
        }

        /// <summary>
        /// タイマーの初期設定
        /// </summary>
        private void TimerSettings()
        {
            this.timer = new DispatcherTimer(DispatcherPriority.Normal);
            this.timer.Interval = new TimeSpan(10);
            this.timer.Tick += new EventHandler(this.DispatcherTimer_Tick);
        }

        /// <summary>
        /// タイマーのTickイベント
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void DispatcherTimer_Tick(object sender, EventArgs e)
        {
            this.joypad.GetJoypadInfomation();
            this.data_TextBlock.Text = string.Join("",this.joypad.buttons);
            
        }

    }
}

JoypadInfomation.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SlimDX.DirectInput;

namespace WpfJoypad
{
    /// <summary>
    /// コントローラーの情報を持つクラス
    /// </summary>
    class JoypadInfomation
    {
        private List<DeviceInstance> directInputList;
        private DirectInput directInput;
        public SlimDX.DirectInput.Joystick gamePad { get; set; }
        public SlimDX.DirectInput.JoystickState state { get; set; }
        public bool[] buttons { get; set; }

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public JoypadInfomation()
        {
            this.directInputList = new List<DeviceInstance>();
            this.directInput = new DirectInput();

            this.directInputList.AddRange(this.directInput.GetDevices(DeviceClass.GameController, DeviceEnumerationFlags.AttachedOnly));
            this.gamePad = new SlimDX.DirectInput.Joystick(this.directInput, this.directInputList[0].InstanceGuid);
        }

        /// <summary>
        /// コントローラーの情報を取得
        /// </summary>
        public void GetJoypadInfomation()
        {
            if (this.gamePad.Acquire().IsFailure) return;
            if (this.gamePad.Poll().IsFailure) return;
            if (SlimDX.Result.Last.IsFailure) return;

            this.state = this.gamePad.GetCurrentState();

            this.buttons = this.state.GetButtons();

            this.gamePad.Unacquire();
        }
    }
}

 実行結果。
f:id:pongeponge:20140403164409j:plain
コントローラーのボタンを押すとFalseがTrueに変わるけど、やたら見づらいw


アナログコントローラ(DUALSHOCK 2)