DirectInputサンプルプログラム・2

 前回作ったサンプルは、ジョイパッドをメインに作ったため、キーボードのほかのキーの状態を取得することはできない。
今回は、キーボードとジョイパッドの情報を別々に取り出すプログラムを作ってみた。ついでに、マウスも使えるようにした。

1.前準備

 myInput.lzhをダウンロードし、解凍するとmyInput.hmyInput.cppという2つのファイルが現れる。
 私が作った基本プログラムに組み込む場合、次のように設定する。

1.プロジェクトの変更

DirectInputを使えるようにプロジェクトの設定を変更する。

  1. 「プロジェクト」→「設定」を選択
  2. 「リンク」タブをクリックし、「オブジェクト/ライブラリ モジュール」に dinput.libライブラリを追加
  3. 追加したら「OK」ボタンをクリック

2.プロジェクトへ追加

解凍した2つのファイルを自分のプロジェクトにインポートする。

3.common.hの修正

common.hにdinput.hmyInput.hをインクルードする。

#include <dinput.h>
#include "myInput.h"

4.WinMain.cppの修正・1

DirectDrawの初期化後、DirectInputオブジェクトの初期化を行う。

/* DirectInputオブジェクトの初期化 */
if (!InitDInput(hThisInst)) return FALSE;

5.WinMain.cppの修正・2

プログラム終了時、DirectInputオブジェクトを開放する。
(case WM_DESTROY:内のReleaseDraw();の前)

ReleaseDInput(); // DirectInputオブジェクトの開放

2.キーボードの情報を取得する

1.キーボードデバイスの設定

 キーボードの情報を取得するには、まずキーボードデバイスを設定する必要がある。これは、DirectInputの初期化(WinMain.cpp内)のあとに、次のように指定する。

/* Keyboard Object の初期化 */
if (!InitKeyboard(hWnd)) return FALSE;

2.キーボード情報の取得

 キーボードの情報(押されているか押されていないか)を格納する変数はmyInput.cppですでに用意してある。取得したいところでGetKeyboardState()という関数を実行すると、状態を取得し、変数に情報を格納する。

// キーボードの状態を取得
GetKeyboardState();

 これにより、diKeyStateという配列にキーボード上のすべてのキーの情報が格納される。

3.調べたいキーが押されているかどうかを調べる

2でキーボードの情報がすべてdiKeyState配列に格納されるため、調べたいキーが押されているかどうかを調べればよい。

// カーソルキーの上が押されているかどうかを調べる
if (diKeyState[DIK_LEFT] & 0x80)
// 押されているときの処理
else
// 押されていないときの処理

[サンプル関数]

 カーソルキー(上下左右のキー)の情報を取得し、状態を表示するサンプルを作ってみた。この関数を参考(になるかどうか判らないが)にし、自分のゲームに合うものを作ってみよう。

//-----------------------------------------------------------------------------
// 関数名 : KeyboardTest()
// 機能概要: キーボードテスト
//-----------------------------------------------------------------------------
static void KeyboardTest(HWND hWnd)
{
    char	buf[256] = "Input Key :";
	
    // キーボードの状態を取得
    GetKeyboardState();

    // 取得した情報を元に押されているキーを調べる
    if (diKeyState[DIK_LEFT] & 0x80)	strcat(buf, "Left ");
    if (diKeyState[DIK_RIGHT] & 0x80)	strcat(buf, "Right ");
    if (diKeyState[DIK_UP]amp; & 0x80)		strcat(buf, "Up ");
    if (diKeyState[DIK_DOWN] & 0x80)	strcat(buf, "Down");

    // 表示
    strOut(200, 50, buf, RGB(255, 255, 255), 10, "MS 明朝", FALSE);

}

※strOutという関数は私の自作関数で、文字列を指定したフォントで表示する。詳しくは「文字配列の文字を表示する」を参照のこと。

4.DirectInputで取得できるキーの種類

 DirectInputでは、すべてのキーの情報を取得できる。代表的なものは次のとおり。

キーコード説明
DIK_A 〜 DIK_ZA〜Zキー
DIK_1 〜 DIK_0メインキーの数字
(テンキー内の数字ではない)
DIK_MINUSメインキーのマイナス(−)記号
(テンキー内のマイナス記号ではない)
DIK_EQUALメインキーのイコール(=)記号
(テンキー内のイコール記号ではない)
DIK_SPACESPACEキー
DIK_ESCAPEESCAPEキー
DIK_TABTABキー
DIK_BACKBACK SPACEキー
DIK_RETURNRETURNキー
DIK_F1 〜 DIK_F15ファンクションキーのF1〜F15
DIK_PRIORPAGE UPキー
DIK_NEXTPAGE DOWNキー
DIK_LCONTROL左CTRLキー
DIK_RCONTROL右CTRLキー
DIK_LSHIFT左SHIFTキー
DIK_RSHIFT右SHIFTキー
DIK_LMENU左ALTキー
DIK_RMENU右ALTキー
DIK_UP DIK_DOWN DIK_RIGHT DIK_LEFT↑↓→←キー
DIK_NUMPAD0 〜 DIK_NUMPAD9テンキーの0〜9
DIK_MULTIPLYテンキーの*
DIK_SUBSTRACTテンキーの−
DIK_ADDテンキーの+
DIK_DESIMALテンキーのピリオド(.)
DIK_NUMPADENTERテンキーのEnter
DIK_DEVIDEテンキーのスラッシュ(/)

3.ジョイパッドの情報を取得するには

1.前準備

 キーボードのキーコード(DIK_〜)はあらかじめDirectInputに定義されているが、ジョイパッドのキーコードは定義されていない。
 そのため、自作のキーコードを作り、それを使うことにした。以下のコードをcommon.hに追加する。

//-----------------------------------------------------------------------------
// Joypad情報用マクロ
//-----------------------------------------------------------------------------
#define BUTTON_UP     0x00000001l	//方向キー上(dijs.IY<0)
#define BUTTON_DOWN   0x00000002l	//方向キー下(dijs.IY>0)
#define BUTTON_LEFT   0x00000004l	//方向キー左(dijs.IX<0)
#define BUTTON_RIGHT  0x00000008l	//方向キー右(dijs.IX>0)
#define BUTTON_A      0x00000010l	//Aボタン(dijs.rgbButtons[0]&0x80)
#define BUTTON_B      0x00000020l	//Bボタン(dijs.rgbButtons[1]&0x80)
#define BUTTON_C      0x00000040l	//Cボタン(dijs.rgbButtons[2]&0x80)
#define BUTTON_X      0x00000080l	//Xボタン(dijs.rgbButtons[3]&0x80)
#define BUTTON_Y      0x00000100l	//Yボタン(dijs.rgbButtons[4]&0x80)
#define BUTTON_Z      0x00000200l	//Zボタン(dijs.rgbButtons[5]&0x80)
#define BUTTON_L      0x00000400l	//Lボタン(dijs.rgbButtons[6]&0x80)
#define BUTTON_R      0x00000800l	//Rボタン(dijs.rgbButtons[7]&0x80)
#define BUTTON_START  0x00001000l	//STARTボタン(dijs.rgbButtons[8]&0x80)
#define BUTTON_M      0x00002000l	//Mボタン(dijs.rgbButtons[9]&0x80)

2.ジョイパッドデバイスの設定

 ジョイパッドの情報を取得するには、まずジョイパッドデバイスを設定する必要がある。これは、DirectInputの初期化(WinMain.cpp内)のあとに、次のように指定する。

/* Joypad Object の初期化 */
if (!InitJoypad(hWnd)) OutputDebugString("Joypad Not Found\n");

[注意]

ジョイパッドが見つからない場合プログラムを終了させるには、if文でreturnすればいい。
しかし、ジョイパッドがない場合はキーボードで動くようにするためには、ここでプログラムを終了させるわけにはいかない。

3.ジョイパッドが接続されているかどうかを確認する

 ジョイパッドの各ボタンが押されているかどうかを取得する前に、ジョイパッドが存在するかどうかを調べ、存在しなければ処理を行わないようにしなければならない。ジョイパッドが存在するかどうかは、ジョイパッドデバイスが作成されたかどうかで調べることができる。

// ジョイパッドがない場合、以下の処理を行わない
if (!pDIJoypad) return;

 上記if文でreturnにならなかった場合、ジョイパッドデバイスが正常に作成されているので、各ボタンの情報(押されているか押されていないか)を取得できる。

4.ジョイパッド情報の取得

ジョイパッドのどのボタンが押されているかを格納する変数はmyInput.cppですでに用意してある。取得したいところでGetJoypadState()という関数を実行すると、状態を取得し、変数に情報を格納する。

// ジョイパッドの状態を取得
GetJoypadState();

 これにより、diJoyStateという配列に、ジョイパッド上のすべてのボタンの情報が格納される。

5.調べたいボタンが押されているかどうかを調べる

調べたいボタンが押されているかどうかは次のように判断する。

// カーソルキーの左が押されているかどうかを調べる
if (diJoyState & BUTTON_LEFT)
// 押されているときの処理
else
// 押されていないときの処理

[サンプル関数]

 ジョイパッドの十字キーの情報を取得し、状態を表示するサンプルを作ってみた。 この関数を参考(になるかどうか判らないが)にし、自分のゲームに合うものを作ってみよう。

//-----------------------------------------------------------------------------
// 関数名 : JoypadTest()
// 機能概要: ジョイパッドテスト
//-----------------------------------------------------------------------------
static void JoypadTest(HWND hWnd)
{
    char	buf[256] = "Joypad :";

    if (!pDIJoypad)	// ジョイパッドがない場合、以下の処理を行わない
    {
        strcat(buf, "無し");
        strOut(200, 60, buf, RGB(255, 255, 255), 10, "MS 明朝", FALSE);
        return;
    }

    // ジョイパッドの状態を取得
    GetJoypadState();

    // 取得した情報を元に押されているキーを調べる
    if (diJoyState & BUTTON_LEFT)	strcat(buf, "Left ");
    if (diJoyState & BUTTON_RIGHT)	strcat(buf, "Right ");
    if (diJoyState & BUTTON_UP)		strcat(buf, "Up ");
    if (diJoyState & BUTTON_DOWN)	strcat(buf, "Down");

    // 表示
    strOut(200, 60, buf, RGB(255, 255, 255), 10, "MS 明朝", FALSE);

}

[注意]

strOutという関数は私の自作関数で、文字列を指定したフォントで表示する。詳しくは「文字配列の文字を表示する」を参照のこと。

4.マウスの使い方

1.マウスデバイスの設定

 マウスの情報を取得するには、まずマウスデバイスを設定する必要がある。これは、DirectInputの初期化(WinMain.cpp内)のあとに、次のように指定する。

/* Mouse Object の初期化 */
if (!InitMouse(hWnd)) return FALSE;

2.前準備

 マウスの状態を取得するのは簡単だが、その情報をどう使うかが問題である。なぜならマウスポインタの位置は座標では取得できないからである。また、ゲームの場面によっては、画面いっぱいにマウスカーソルを動かしたり、動く位置を限定したりする必要もあるだろう。マウスカーソルの移動速度も場合によっては変えたいかもしれない。また、マウスカーソルの画像も用意する必要がある。
 そういったことを考慮し、マウスの絶対座標や移動速度などを格納する構造体を場面ごとに作成し、DirectInputから取得したマウスの情報を元に、構造体の情報を書き換えるという方法をとることにした。

  1. まず、common.hにマウス情報を格納する構造体の型を宣言する。
    /* マウスポインタの情報 */
    typedef struct _MSTATE {
        RECT    moveRect;     // 画面上で動ける範囲
        int     x;            // X座標
        int     y;            // Y座標
        bool    lButton;      // 左ボタン
        bool    rButton;      // 右ボタン
        bool    cButton;      // 真ん中ボタン
        int     moveAdd;      // 移動量
        RECT    imgRect;      // マウス用画像矩形
        int     imgWidth;     // マウス画像幅
        int     imgHeight;    // マウス画像高さ
    } MSTATE;
  2. 次に、マウスの情報を格納する変数を作成する。たとえばスタート画面でメニューを選ぶ際にマウスを使用したい場合、Start.cpp内のローカル変数宣言で変数を宣言する。
    static MSTATE MState; // マウスポインタ情報
  3. 次に、初期化処理(StartInit関数内)で、マウスポインタ情報の初期化を行う。
    //------------------------------------------------------- マウスポインタ情報の初期化
    SetRect(&MState.moveRect, 10, 10, 630, 470);	// マウスカーソルの動く範囲
    MState.x = MState.moveRect.left;	// マウスカーソルのX座標を初期化
    MState.y = MState.moveRect.top;	// マウスカーソルのY座標を初期化
    MState.lButton = false;	// 左ボタンの情報を初期化
    MState.rButton = false;	// 右ボタンの情報を初期化
    MState.cButton = false;	// 中央ボタンの情報を初期化
    MState.moveAdd = 2;	// マウスカーソルの移動量を設定
    SetRect(&MState.imgRect, 400, 0, 420, 20);	// マウスカーソル画像の矩形を設定
    MState.imgWidth = MState.imgRect.right - MState.imgRect.left;	// 画像の幅を計算
    MState.imgHeight = MState.imgRect.bottom - MState.imgRect.top;	// 画像の高さを計算

3.マウス情報の取得

 マウスの情報(カーソルがどのように動いたか、ボタンは押されているか押されていないか)を格納する変数はmyInput.cppですでに用意してある。取得したいところでGetMouseState()という関数を実行すると、状態を取得し、変数に情報を格納する。

// マウスの状態を取得
GetMouseState();

 取得した情報を元に、マウス情報を更新する。更新するプログラムは次のとおり。

// 取得した情報を元にマウスの情報を更新
MState.x += (diMouseState.lX * MState.moveAdd);
MState.y += (diMouseState.lY * MState.moveAdd);
if (MState.x < MState.moveRect.left) MState.x = MState.moveRect.left;
if (MState.x > MState.moveRect.right - MState.imgWidth) MState.x = MState.moveRect.right - MState.imgWidth;
if (MState.y < MState.moveRect.top) MState.y = MState.moveRect.top;
if (MState.y > MState.moveRect.bottom - MState.imgHeight) MState.y = MState.moveRect.bottom - MState.imgHeight;
(diMouseState.rgbButtons[0] & 0x80) ? MState.lButton = true : MState.lButton = false;
(diMouseState.rgbButtons[1] & 0x80) ? MState.rButton = true : MState.rButton = false;
(diMouseState.rgbButtons[2] & 0x80) ? MState.cButton = true : MState.cButton = false;

 これにより、MStateという構造体変数に、カーソルの位置や、ボタンの状態が格納される。カーソルの位置は、MState.xとMState.yである。ボタンが押されているかどうかは、MState.lButton、MState.rButton、MState.cButtonがそれぞれtrueかfalseかを調べる。

[サンプル関数]

 マウスの情報を取得し、状態を表示するサンプルを作ってみた。この関数を参考(になるかどうか判らないが)にし、自分のゲームに合うものを作ってみよう。

//-----------------------------------------------------------------------------
// 関数名 : MouseTest()
// 機能概要: マウステスト
//-----------------------------------------------------------------------------
static void MouseTest(HWND hWnd)
{
    HRESULT			hRet;

    // マウスの状態を取得
    GetMouseState();

    // 取得した情報を元にマウスの情報を更新
    MState.x += (diMouseState.lX * MState.moveAdd);
    MState.y += (diMouseState.lY * MState.moveAdd);
    if (MState.x < MState.moveRect.left) MState.x = MState.moveRect.left;
    if (MState.x > MState.moveRect.right - MState.imgWidth) MState.x = MState.moveRect.right - MState.imgWidth;
    if (MState.y < MState.moveRect.top) MState.y = MState.moveRect.top;
    if (MState.y > MState.moveRect.bottom - MState.imgHeight) MState.y = MState.moveRect.bottom - MState.imgHeight;
    (diMouseState.rgbButtons[0] & 0x80) ? MState.lButton = true : MState.lButton = false;
    (diMouseState.rgbButtons[1] & 0x80) ? MState.rButton = true : MState.rButton = false;
    (diMouseState.rgbButtons[2] & 0x80) ? MState.cButton = true : MState.cButton = false;

    // 座標表示
    char	buf[80];
    sprintf(buf, "MousePoint (%d, %d) %d %d %d",
        MState.x, MState.y, MState.lButton, MState.rButton, MState.cButton);
    strOut(200, 70, buf, RGB(255, 255, 255), 10, "MS 明朝", FALSE);

    // マウス画像(カーソル)表示
    hRet = myBltFast(g_pDDSBack, MState.x, MState.y, g_pDDSChara, &MState.imgRect, DDBLTFAST_SRCCOLORKEY);
    if ( hRet != DD_OK )
        return;

}

[注意]

マウスの状態だけでなく、実際に画像も表示している。

5.総合サンプル

 基本プログラムに上記処理をすべて加えた実行結果及びそのソースを、以下からダウンロードできるようにした。
 上記説明でうまくいかない場合の参考にしてください。

6.今後の予定

 マウスの制御がどうも面倒になってしまった。もう少し判りやすいものにならないか、考え直してみよう。


[ TOP ]