ゲーム開発9:入力処理2

90353511.jpg入力処理のCInputクラスです。

前回CInputBaseクラスにて、キーボードとゲームパッドから情報を取得する設定を行いました。今回は取得した情報をゲームで使える値に変換します。

ゲームで使う値は移動のxとy、そして決定キーa、キャンセルキーb、選択キーcとします。アクションゲームだったら、決定キーが攻撃になったりキャンセルキーがジャンプになったりします。ともかくそれをKEYCODE構造体としてまとめておきます。

ボタンが押された際、キーボードからは配列が、ゲームパッドからは構造体が返されます。押されたボタンを確認するには、dinput.hに書かれた定義を参照して、ビットが立っているかどうかで判断します。

ところでゲームパッドの十字キーは、アナログで最大0~65535まで値を取ったりするらしいので、閾値を10にして、ちょっとでも押されたら反応するようにしました。ホントはゲームパッドが返した情報を元に、ちゃんと決めないといけないんだけどね。持ってるゲームパッドは0か1000かの2択だったし。

押されたボタンがわかったら、それをKEYCODE構造体に格納して返せばOKです。ちなみにPressKey()では過去に押されたボタンの履歴を参考に、同時押しを抑制しています。

これでスプライトを動かす事が出来るようになりました。音楽以外は一通り基底部分が完成しましたので、次回はゲームの仕様を考えますか。

//---------------------------------------------------------
typedef struct {
 int x; // X軸
 int y; // Y軸
 int a; // 決定
 int b; // キャンセル
 int c; // 選択
} KEYCODE;

#define KEYDOWN(name, key) (name[key] & 0x80)

//---------------------------------------------------------
// キーボード入力取得
void CInput::GetKeyboard(KEYCODE *keycode)
{
 char buffer[256];
 HRESULT hr;

 // キーボードステータス取得
 hr=ProcessKeyboard(buffer);
 if FAILED(hr) {
  return;
 }

 // 6
 if (KEYDOWN(buffer, DIK_NUMPAD6)) {
  keycode->x=1;
 }
 // 4
 else if(KEYDOWN(buffer, DIK_NUMPAD4)) {
  keycode->x=-1;
 }

 // 8
 if (KEYDOWN(buffer, DIK_NUMPAD8)) {
  keycode->y=-1;
 }
 // 2
 else if(KEYDOWN(buffer, DIK_NUMPAD2)) {
  keycode->y=1;
 }

 // 右
 if (KEYDOWN(buffer, DIK_RIGHT)) {
  keycode->x=1;
 }
 // 左
 else if(KEYDOWN(buffer, DIK_LEFT)) {
  keycode->x=-1;
 }

 // 上
 if (KEYDOWN(buffer, DIK_UP)) {
  keycode->y=-1;
 }
 // 下
 else if (KEYDOWN(buffer, DIK_DOWN)) {
  keycode->y=1;
 }

 // Z
 keycode->a=0;
 if (KEYDOWN(buffer, DIK_Z)) {
  keycode->a=1;
 }

 // X
 keycode->b=0;
 if (KEYDOWN(buffer, DIK_X)) {
  keycode->b=1;
 }

 // C
 keycode->c=0;
 if (KEYDOWN(buffer, DIK_C)) {
  keycode->c=1;
 }

 // エンター
 if (KEYDOWN(buffer, DIK_RETURN) || KEYDOWN(buffer, DIK_NUMPADENTER)) {
  keycode->a=1;
 }

 // スペース
 if (KEYDOWN(buffer, DIK_SPACE)) {
  keycode->b=1;
 }
}

//---------------------------------------------------------
// ジョイスティック入力取得
void CInput::GetJoystick(KEYCODE *keycode)
{
 DIJOYSTATE js;
 HRESULT  hr;

 // ジョイスティックステータス取得
 ZeroMemory(&js, sizeof(DIJOYSTATE));
 hr=ProcessJoystick(&js);
 if FAILED(hr) {
  return;
 }

 // X軸
 if (js.lX>10) {
  keycode->x=1;
 }
 if (js.lX<-10) {
  keycode->x=-1;
 }

 // Y軸
 if (js.lY>10) {
  keycode->y=1;
 }
 if (js.lY<-10) {
  keycode->y=-1;
 }

 // 1ボタン
 if (KEYDOWN(js.rgbButtons, 0)) {
  keycode->a=1;
 }

 // 2ボタン
 if (KEYDOWN(js.rgbButtons, 1)) {
  keycode->b=1;
 }

 // 3ボタン
 if (KEYDOWN(js.rgbButtons, 2)) {
  keycode->c=1;
 }
}

//---------------------------------------------------------
// キー入力取得
void CInput::PressKey(KEYCODE *keycode)
{
 static int old_xy=0;  // 前回の移動キー
 KEYCODE  di_key, di_joy;
 int   new_x, new_y;

 ZeroMemory(keycode, sizeof(KEYCODE));

 // キーボード&ジョイスティック取得
 ZeroMemory(&di_key, sizeof(KEYCODE));
 GetKeyboard(&di_key);
 ZeroMemory(&di_joy, sizeof(KEYCODE));
 GetJoystick(&di_joy);

 // X軸
 new_x=di_key.x;
 if (di_joy.x!=0) {
  new_x=di_joy.x;
 }

 // Y軸
 new_y=di_key.y;
 if (di_joy.y!=0) {
  new_y=di_joy.y;
 }

 // 前回の軸を見て移動軸を決定
 if (new_x!=0 && new_y!=0) {
  if (old_xy==0) {
   keycode->y+=new_y;
  }
  else {
   keycode->x+=new_x;
  }
 }
 else {
  // 片方だけ移動
  keycode->x+=new_x;
  keycode->y+=new_y;
  if (new_y==0) {
   old_xy=0;
  }
  else {
   old_xy=1;
  }
 }

 // 決定ボタン
 keycode->a=di_key.a;
 if (di_joy.a!=0) {
  keycode->a=di_joy.a;
 }

 // キャンセルボタン
 keycode->b=di_key.b;
 if (di_joy.b!=0) {
  keycode->b=di_joy.b;
 }

 // 選択ボタン
 keycode->c=di_key.c;
 if (di_joy.c!=0) {
  keycode->c=di_joy.c;
 }
}

ゲーム開発9:入力処理2」への2件のフィードバック

  1. ざっと見、Cとそっくりだね。
    キーでもチャタリング吸収とか下層の処理が要らないってのは組み込み系と違って羨ましい。

    俺もぼちぼちアプリでも作ってみたいなぁと思うんだけど、なかなか時間が…。(;´Д`)

  2. C++で組んでるので、構文的にはそっくりですね。それに、今はクラスの定義部分を省略してますし。

    下層処理がいらないのがDirectXを使う強みです。逆に自作してたら、ライブラリ作る時点で挫折しますw

    プログラム開発は時間かかりますからね…

コメントを残す

メールアドレスが公開されることはありません。