電子書籍の厳選無料作品が豊富!

現在、DirectXでゲームを作っているのですが、上と右や下と左の方向キー同時押しを認識させたいのですがやり方がわかりません。
現在は、VK_UP,VK_DOWN,VK_LEFT,VK_RIGHTで4方向は認識できるのですが。右上,左上,右下,左下も含めた8方向を認識させたいのです。
やり方や方法がわかるサイトでもかまいませんのでお願いします。

A 回答 (4件)

 こんにちは。



 ゲームの種類にもよるのですが、DirectX環境下と言う事で、秒間60回描写辺りを目安に作っているゲームなら、アイドリングループ位は持っているでしょうから、その中でGetKeyboardState()を呼び出して検出するのが手っ取り早いです。
 ただ、ウィンドウのメッセージループ外では無効な上、ウィンドウがタスクバー化したり、フォーカスを失うと、一気に入力を受け付けなくなるので、DirectInputの使用が最も無難だと思います(何処でも現在の入力状態が受け取れる)。
 初期化は面倒ですが、呼び出し方としてはGetKeyboardState()と大した変わりがありません(良く似ていると言う事です)。

+----------------------------------------------------------------+
BYTE key[256] = {0};
::GetKeyboardState(key);
//左後方大ジャンプ成立
if((key[VK_UP] & 0x80) && (key[VK_LEFT] & 0x80))
{
 ココでキャラが左上に大ジャンプする
}
+----------------------------------------------------------------+
BYTE Key[256] = {0};
g_pKeyboard->GetDeviceState(256, Key);
//左後方大ジャンプ成立
if((key[DIK_UP] & 0x80) && (key[DIK_LEFT] & 0x80))
{
 ココでキャラが左上に大ジャンプする
}
+----------------------------------------------------------------+

 尚、キーボードの同時押しについては既出の通り、DirectInputを使用しても受け付けない組み合わせがあります。

 DirectInputに関しては以下を参考にして見て下さい。
 http://www.shader.jp/xoops/html/masafumi/directx …
 http://oshiete1.goo.ne.jp/qa4345138.html
 http://oshiete1.goo.ne.jp/qa4312916.html
    • good
    • 0

蛇足ですが。



当方の回答の例では「キーボードイベントを受け取って、キーの状態により変数を操作する部分」と「キーの状態を持つ変数の値により、方向を認識する部分(つまり、移動の処理をする部分)」は「別々」にしてあります。

何故なら、ゲームの場合「自機(自分)は、一旦動き出したら一定速度で動く筈」であり、キーボードイベントが来た時しか動かないのは変です。

なので「キーボードイベントを処理する場所で、自機(自分)を移動させる処理をしてはいけない」のです。

自機(自分)を移動させる処理は、画面表示1回につき1回ごと(つまり、1フレームごと)に行わねばならず、キーボードイベントとは別のタイミングで行わねばなりません。

そのため、2つの処理を「別々」にしてあるのです。
    • good
    • 0

WM_KEYDOWN、WM_KEYUPメッセージをキャプチャして下さい。



上下左右キーそれぞれについて、押下中かどうかの状態を持つ変数を1つ用意します。

そして、変数のビット0~3を、上下左右キーの状態に割り当てます。

WM_KEYDOWNイベントを受け取ったら、以下のようにします。

・WPARAMがVK_UPだったら変数のビット0を1にします。
・WPARAMがVK_DOWNだったら変数のビット1を1にします。
・WPARAMがVK_LEFTだったら変数のビット2を1にします。
・WPARAMがVK_RIGHTだったら変数のビット3を1にします。

WM_KEYUPイベントを受け取ったら、以下のようにします。

・WPARAMがVK_UPだったら変数のビット0を0にします。
・WPARAMがVK_DOWNだったら変数のビット1を0にします。
・WPARAMがVK_LEFTだったら変数のビット2を0にします。
・WPARAMがVK_RIGHTだったら変数のビット3を0にします。

具体的には、以下のようになります。

事前に変数KeyBitsを用意し0に初期化しておいて下さい。

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)
{
 switch ( msg )
 {
 case WM_KEYDOWN:   // キーが押されたとき
  switch ( wp )
  {
  case VK_UP:
   KeyBits |= 1;
   return 0;
  case VK_DOWN:
   KeyBits |= 2;
   return 0;
  case VK_LEFT:
   KeyBits |= 4;
   return 0;
  case VK_RIGHT:
   KeyBits |= 8;
   return 0;
  }
  break; // 特に処理しないキーはDefWindowProc()に任せる
 case WM_KEYUP:   // キーが離されたとき
  switch ( wp )
  {
  case VK_UP:
   KeyBits &= ~1;
   return 0;
  case VK_DOWN:
   KeyBits &= ~2;
   return 0;
  case VK_LEFT:
   KeyBits &= ~4;
   return 0;
  case VK_RIGHT:
   KeyBits &= ~8;
   return 0;
  }
  break; // 特に処理しないキーはDefWindowProc()に任せる
 case WM_DESTROY:   // ウィンドウが破棄されるとき
  PostQuitMessage( 0 );
  return 0;
 }
 return DefWindowProc( hWnd, msg, wp, lp );
}

で、変数KeyBitsの値により、以下のように場合分けします。

 switch ( KeyBits )
 {
 case 0x01: ///↑を押している
 case 0x0d: ///↑→←を押している
  上方向の処理
  break;
 case 0x02: ///↓を押している
 case 0x0e: ///↓→←を押している
  下方向の処理
  break;
 case 0x04: ///←を押している
 case 0x07: ///↑↓←を押している
  左方向の処理
  break;
 case 0x08: ///→を押している
 case 0x0b: ///↑↓→を押している
  右方向の処理
  break;
 case 0x09: ///↑→を押している
  右上方向の処理
  break;
 case 0x0a: ///↓→を押している
  右下方向の処理
  break;
 case 0x05: ///↑←を押している
  左上方向の処理
  break;
 case 0x06: ///↓←を押している
  左下方向の処理
  break;
 case 0x00: //どれも押してない
 case 0x03: //↑↓を押している
 case 0x0c: //→←を押している
 case 0x0f: //↑↓→←を押している
  // 何もしない
  break;
 }

なお、ウィンドウ上でキーを押したままにして、マウスで別ウィンドウに移動して、別ウィンドウがアクティブになった状態でキーを離すと、元のウィンドウにはWM_KEYDOWNのみが送られ、WM_KEYUPが送られない場合があります。

つまり、矢印キーを押している最中に別ウィンドウに移ってから、元のウィンドウに戻ると「キーを押してないのに、矢印キーがいつまでも押しっぱなしの状態のまま」になる事があります。

なので「ウィンドウが非アクティブになった時」に「全部の矢印キーが離された事にする」と言う細工が必要です(前述の例で言えば、KeyBits変数を0にしてしまう)

また、キーのオートリピート機能により、WM_KEYDOWNイベントが連続で大量に発生する事があるので「WM_KEYDOWNが連続で発生しても大丈夫」な書き方をする必要があります。
    • good
    • 0

キーボードの同時押しに関しましては、


GetKeyboardState()が使えると思いますので、
参照してみてください。

ただし、キーの組み合わせや、キーボードの種類によっては、
同時押しを正しく取得出来る保証はありません。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!