Nodachisoft Nodachi Sword Icon
  
@あまじ✎ 2021年3月13日に更新

第3章6 リアルタイムなキーボード入力制御

イチからゲーム作りで覚えるC言語
第3章5 エスケープシーケンスで文字の色、背景の色を変更 : PREV
NEXT : 第3章7 ネット接続してWebからデータを取得 :

概要

Windows API を使い、コンソール画面への入力をリアルタイムに(即時に) 取得する方法を確認していきます。

過去の記事では scanf 関数などを使って、文字列の入力を受付して、 エンターが入力された段階でプログラムが文字列を受け取る、という仕組みでした。

しかし、これではリアルタイムに動作するアプリへの入力が処理できないですね。

例えばキャラクタを FPS などでよくある「WASD」キーや、十字キーで操作するなど。 毎回入力待ちでアプリが停止して知っては、成り立たないです。

確認用コード

スペースキーの入力があったら終了するプログラムです。

 
input_ex.c
#include <stdio.h>
#include <windows.h>
int main() {
   printf("キーボードでスペースキーを押したら終了します\n");
   while(1) {
      if(GetAsyncKeyState(VK_SPACE) & 0x01 ) {
         // スペースキーが押された!
         printf("スペースキーが押されました\n");
         break;
      }
      Sleep(1);
   }
}

実行すると下のような結果になりました。

実行結果
キーボードでスペースキーを押したら終了します
スペースキーが押されました

スペースキー以外をおしても画面上になにも反応はでないです。 スペースキーを押すと即座に画面上に「スペースキーが押されました」と表示がされるかと思います。

コードの内容確認

今回、キーボードの入力を受け付けている部分のコードです。

 
input_ex.c
while(1) {
    if(GetAsyncKeyState(VK_SPACE) & 0x01 ) {
        // スペースキーが押された!
        printf("スペースキーが押されました\n");
        break;
    }
    Sleep(1);
}

while(1){ ・・・プログラム・・・ } という書き方で、while 文の中身のプログラムを無限ループできます。

while 文の条件式は true でも良いです。条件が "真" と評価されていれば繰り返されます。

5 行目で、GetAsyncKeyState 関数が登場しています。 これは Windows API を試用した関数で、その時点でのキーボードの状態を確認して結果を返す関数です。

確認したい対象のキーボードのキーを引数で渡します。

今回は VK_SPACE という定数を引数に代入しています。

VK_SPACE という定数も windows.h ヘッダーをインクルードすることで参照できるようになります。

これは、キーボーボードの「スペースキー」を表す定数です。 他にもマウスやテンキーボードのそれぞれのキーを表す定数もあらかじめ用意されており、 それぞれキーの状態を取得できます。

代表的なキーボードなどの入力確認定数一覧

入力内容 定数
VK_F1 F1キー
VK_NUMPAD0 ~ 9 テンキーの 0 ~ 9
VK_LEFT ←キー
VK_UP ↑キー
VK_RIGHT →キー
VK_DOWN ↓キー
VK_LBUTTON マウスの左ボタン
VK_RBUTTON マウスの右ボタン
VK_MBUTTON マウスの中央ボタン

0~9、A~Z キーは直接、数字で入力します。数字(キーコード)とキーボードのキーの対応表を下に乗せておきます。

コード キー コード キー コード キー コード キー コード キー
0x30 0 0x31 1 0x32 2 0x33 3 0x34 4
0x37 7 0x38 8 0x39 9
0x41 A 0x42 B 0x43 C 0x44 D 0x45 E
0x47 G 0x48 H 0x49 I 0x4A J 0x4B K
0x4D M 0x4E N 0x4F O 0x50 P 0x51 Q
0x53 S 0x54 T 0x55 U 0x56 V 0x57 W
0x59 Y 0x5A Z

テンキーのキーボードの 0~9 はまた別のキーコードが割り当てられていますので注意が必要です。

キーボードの状態

GetAsyncKeyState 関数で対象のキーボードの値を参照していると、 状態は下の用に切り替わっていきます。

入力の状態遷移

  • なにもキーボードを触っていないときは、A の状態が続きます。
  • キー入力された時、次に GetAsyncKeyState 関数でキーコードを参照すると 1 度だけ B の状態であることが返ってきます。
  • キーが押されている間は、GetAsyncKeyState 関数はキーコードの C の状態を返してきます。
  • キーを放すとGetAsyncKeyState 関数は A の状態に戻ります。
  • キーをずっと押しっぱなしだと一定時間の間隔で A → B → C → B → C → B → C → B → ・・・ という風に B と C を繰り返す状態となります。

それぞれの状態は下で判定できます。

状態 判定方法
押していない状態 if ( GetAsyncKeyState(キーコード) == 0 ) { ・・・ }
キー入力時 if ( GetAsyncKeyState(キーコード) & 0x01 ) { ・・・ }
押されている間の状態 if (GetAsyncKeyState(キーコード) & 0xff00 != 0 ) { ・・・ }

補足:Sleep関数が while文の中に入っている意味

while の無限ループの中に以下のSleep命令が含まれています。

 
input_ex.c
while(1) {
    if(GetAsyncKeyState(VK_SPACE) & 0x01 ) {
        // スペースキーが押された!
        printf("スペースキーが押されました\n");
        break;
    }
    Sleep(1);
}

この 10 行目の Sleep 文がなくともプログラムは動作しますが、 Windows OS の動作が不安定になる可能性があります。

無限ループ処理などの中で Sleep 文を入れることで、このタイミングで CPU はこのプログラムの処理を中断して休むことができます。 Windows などの OS は複数のプログラムを同時に動かすことができるマルチタスクと呼ばれる仕組みが根本にあり、 一つのプログラムだけを集中して実行するのではなく、実行敷いているプログラムを非常に短い感覚で切替て他のプログラムも同時に動かしています。

この Sleep 文を定期的に実行することで、CPU はこのタイミングで、他のプログラムの処理に切り替えることができる目印となります。 もしこの Sleep 文がないと、CPU はこのプログラムの実行だけに集中してしまうので、Windows OS が動くための基本的なプログラムの 処理が行われずに、動作が不安定になってしまう可能性がある、ということです。

参考

イチからゲーム作りで覚えるC言語
第3章5 エスケープシーケンスで文字の色、背景の色を変更 : PREV
NEXT : 第3章7 ネット接続してWebからデータを取得 :
 
 
送信しました!

コメント、ありがとうございます。

なんかエラーでした

ごめんなさい。エラーでうまく送信できませんでした。ご迷惑をおかけします。しばらくおいてから再度送信を試していただくか、以下から DM などでご連絡頂ければと思います。

Twitter:@NodachiSoft_jp
お名前:
 
連絡先:
 
メッセージ:
 
戻る
内容の確認!

以下の内容でコメントを送信します。よろしければ、「送信」を押してください。修正する場合は「戻る」を押してください

お名前:
 
連絡先:
 
メッセージ:
 
Roboto からの操作ではないという確認のため確認キーを入れてください。
確認キー=95
戻る
 / 
送信確認へ
コメント欄
コメント送信確認へ

関連ありそうな記事(5件)です!

第4章3 C言語コンソール上で迷路脱出プログラム・迷路の自動生成

#C11仕様#C言語#ゲームプログラミング✎ 2021-05-15
C言語のコンソールゲームで迷路脱出ゲームプログラムの作り方を確認します。迷路は自動生成されます
広告領域
追従 広告領域
目次
第3章6 リアルタイムなキーボード入力制御
第3章6 リアルタイムなキーボード入力制御
概要
概要
確認用コード
確認用コード
コードの内容確認
コードの内容確認
キーボードの状態
キーボードの状態
補足:Sleep関数が while文の中に入っている意味
補足:Sleep関数が while文の中に入っている意味
参考
参考
Nodachisoft © 2021