をるふちゃんのブログ

めもっぽいやつ

DirectInputとは【自分用まとめ】

概要

アプリケーションがバックグラウンドで動作していても、基本的な入力デバイスからデータを取得することができる。
DirectX8 SDKが必要。
ちなみにDirectX8から更新されていないのには深いわけがあるらしい。
最近はXInputなるものを推奨していて、Windowsストアアプリ(Xbox版)などはそちらを使えと言われたり。
通常のアプリではWindowsメッセージを使った実装を推奨されている。
が、ゲーム動かすならドライバレベルで動作するほうが楽っちゃ楽かも。
だいたい入出力APIなんて16年経ってもそう変わるものではないのだろう。

動作について

デバイスドライバを直接叩く。
そのためWindowsのマウス・キーボードメッセージは抑制または無視される。
さらに、ユーザがコントロールパネルで行ったマウス・キーボードの設定も無視するが、入力デバイスに直接設定されているキャリブレーションなどは使用する。
※ゲーミングマウスや一部のジョイスティックなどの設定は生きるということ。

キーボードの文字反復の設定は認識しない(押下と解放を反復なしのイベントとして認識し、押しっぱなしにしても続けて入力されない)。
これはつまりキーの物理的な状態のみに着目し、Windowsで解釈されるイベントには関与しないということでもある。
また文字変換や翻訳は実行しない。

マウスもドライバレベルで直接動作するので、ウィンドウアプリケーションについてマウスデータを解釈するWindowsのサブシステムをバイパスする。
排他モードで取得した場合はマウスメッセージを抑制するのでWindowsは標準カーソルを表示できない。

また、マウスの加速やボタン機能の入れ替えなどのコントロールパネルの設定は無視される(ドライバレベルの設定ならば認識する)。

文字コードサポート

ANSIまたはUnicode
#define UNICODE と定義されている場合は、コンパイル時にUnicode バージョンが使用される。

用語

バイ

キーボード・マウス・ジョイスティックその他の入力デバイスのこと。

DirectInput オブジェクト

COMモデルでIDirectInput8 インターフェイスをサポートする。

DirecInputDevice オブジェクト

IDirectInputDevice8 インターフェイスインスタンス化し、各種の入力デバイスを表す。
タッチパッド付きキーボードなどは複数のDirectInputDeviceで表される。

バイスオブジェクト

DirectInputDevice オブジェクト上のキー・ボタン・トリガなどを表す。
バイスオブジェクト インスタンスとも呼ぶ。

ジョイスティック

DirectInputにおいては、マウス・キーボード以外のすべての種類の入力デバイスのことを総称してジョイスティックと呼ぶ。
入出力両方を処理するジョイスティックオブジェクトを作成することもできる。

流れ

1. DirecInput オブジェクトを作成

このオブジェクトのメソッドを使ってデバイスを列挙、DirectInputバイスオブジェクトを作成する。

2. デバイスを列挙

システムマウス・キーボード以外を使う場合は省略してもよし。
ユーザのシステムで、それ以外に使用可能な入力デバイスがある場合は列挙する。
DirectInputに設定した基準と一致したデバイスを検出したらその機能を調べることができ、一意なIDを取得する。

IDirectInputDevice8::EnumObjects メソッド

使用可能なデバイス オブジェクトの数と種類を確認する。
個別のデバイスオブジェクトは DIDEVICEOBJECTINSTANCE 構造体で記述される。

3. DirecInputDeviceオブジェクトの作成

使用するデバイスごとにDirecInputDeviceオブジェクトを作成する。
列挙時に取得した一意のIDを使う。
システムマウス・キーボードは標準の一意の識別子(GUID)を使用できる。

4. デバイスのセットアップ

バイスの、他アプリケーションやシステムとの共有の方法(協調レベル)を決定する。
データパケット内でデバイスを識別するフォーマットを決める。
イベントを取得する場合、バッファサイズの設定も必要。
ジョイスティック等の場合値の範囲も設定できる。

5. デバイスを取得

バイスからデータを受信できるようになったということをDirectInputに知らせる。

6. データを取得

ループ毎などで、各デバイスの現在の状態・最後の取得以降に発生したイベントの記録を取得。
イベント駆動型に設定することもできる。

7. データに基づいて処理を行う

ゲームの処理など。

8. DirectInputを終了

終了する前にアプリは全てのデバイスの取得を解除し、各種オブジェクトを解放する必要がある。

参考

DirectInput の概要 (MSDN)
DirectInput について (MSDN)

Boost導入メモ

MSVCだとどうしたらいいのってなる

ダウンロード

とりあえずboost.orgから最新版を落としてくる。
boost_1_62_0.zipをダウンロードした。

解凍

何も考えずにC:\直下にboostというディレクトリを作り、UnZipして出てくるboost_1_62_0をその中に放り込む。
以下のようになる。

C:
   |-boost
      |-boost_1_62_0

ここで色々面倒なので環境変数BOOST_ROOTC:\boost\boost_1_62_0を設定しておいた。
これで%BOOST_ROOT%とすればアクセスができる。

一応これでヘッダオンリーのライブラリ部分は使えるようになるようだ。
というか、使えた。

動作確認

boost.orgのサンプルコードほぼそのままで恐縮であるが、以下のコードが通ればうまくいっている。
もっとも、解凍してパスを通すだけなのだが。

#include <boost/lambda/lambda.hpp>
#include <iostream>
#include <iterator>
#include <algorithm>

int main() {
    std::for_each( std::istream_iterator<int>( std::cin ), std::istream_iterator<int>(), std::cout << (boost::lambda::_1 * 3) << "\n" );
}

MSVCの場合、プロジェクト設定で追加のインクルードディレクトリに$(BOOST_ROOT)を追加する必要がある。

リンクライブラリを要求される

調子に乗ってコードを書いていくと以下のようなエラーを吐く。

1>LINK : fatal error LNK1104: ファイル 'libboost_regex-vc140-mt-gd-1_62.lib' を開くことができません。

.lib.dllといったリンクライブラリを要求してきている(つまりヘッダオンリーではない関数を呼ぼうとした)
ということなので、これらのパスを通す必要があるわけだが、これらはboostの配布ファイルには直接同梱されていないので自分でビルドする必要がある。

リンクライブラリのビルド

幸いなことに、簡単にできるよう用意されているのでマニュアルに従って実施する。
まず%BOOST_ROOT%ディレクトリ直下にあるbootstrap.batを叩く。
続いて%BOOST_ROOT%ディレクトリでコマンドプロンプトを起動する。

コマンド.\b2と押下したら仮眠をとる。
※というのも、端末の冷却装置がboostするくらい熱くなりとても時間がかかる。
ともあれ、気づいたら%BOOST_ROOT%\stage\libにわんさとリンクライブラリが生産されている。

あとは適切なディレクトリパス(%BOOST_ROOT%\stage\lib)をプロジェクト設定の「リンカ-全般-追加のライブラリディレクトリ」に設定すれば良い。

64bitでも動かしたい場合

b2に色々と情報を与えてやらなければならない。
オプションの意味については公式のマニュアルに譲るとして、
せっかくなので32と64bit版それぞれ.dll.lib版を作ることとしよう。

%BOOST_ROOT%ディレクトリにて以下のコマンドを叩く。

b2 toolset=msvc-14.0 threading=multi variant=debug,release link=static runtime-link=static architecture=x86  address-model=32 --stagedir=stage/x86 -j 4 --without-python
b2 toolset=msvc-14.0 threading=multi variant=debug,release link=shared runtime-link=shared architecture=x86 address-model=32 --stagedir=stage/x86 -j 4 --without-python
b2 toolset=msvc-14.0 threading=multi variant=debug,release link=static runtime-link=static architecture=x86 address-model=64 --stagedir=stage/x64 -j 4 --without-python
b2 toolset=msvc-14.0 threading=multi variant=debug,release link=shared runtime-link=shared architecture=x86 address-model=64 --stagedir=stage/x64 -j 4 --without-python

この端末は2コア4スレッドのため、-j 4オプションを付けている。適宜調整されたい。
私はpythonは使わないため最後に--without-pythonオプションを付けた。これも必要に応じて削除すること。

それと私はVisual Studio 2015を使っているため--toolset=msvc-14.0とした。
このオプションはつけなくても適切なコンパイラを使ってくれるようであるが念のため付け加えておいた。

これによりディレクトリ構成は以下のようになる。

%BOOST_ROOT%
   |- stage
      |-x64
         |-lib
      |-x86
         |-lib