ゲーム制作講座4

4.キーボードで絵を動かそう


 前回までで、見苦しくなく絵を動かす方法を習得しました。今度はその絵をキーボードで自在に
動かしてみましょう。

 絵をキーボードの入力で自在に動かすにはまずキーボードの入力状態を知る方法を覚えなくては
なりません。ここではまずキーボードの入力状態を知る方法を覚えましょう。
 DXライブラリはゲームに使えそうな機能は一通り揃っていますので、キーボードの入力状態を
知るための関数もしっかり用意されています。
 その関数の名前は CheckHitKey 、どのキーの入力状態を知りたいのかを指し示す引数を一つ取る
関数です。関数リファレンスをみて頂ければ全部載っていますが、とりあえず今必要なキーは
上下左右の方向キーの入力状態ですので、使う引数は次の4つになります。

KEY_INPUT_UP : ↑キーの入力状態
KEY_INPUT_DOWN : ↓キーの入力状態
KEY_INPUT_LEFT : ←キーの入力状態
KEY_INPUT_RIGHT : →キーの入力状態

 そして CheckHitkey 関数の戻り値は指定したキーが押されていれば1押されていなければ0
返ってきます。

 例えば↓キーが押されているか知りたい場合は

 CheckHitKey( KEY_INPUT_DOWN )

 さらに↓キーが押されていたら変数aに数値の12を代入したい場合は

 if( CheckHitKey( KEY_INPUT_DOWN ) == 1 )
 {
   a = 12 ;
 }

 とすることで可能です。
 なお KEY_INPUT_UP などこれらの表記はすべて #define で定義されたただの数値です、どのキーが
どの数値なのかは意識する必要はありません。

 さてCheckHitKey 関数の使い方は分かっていただけたでしょうか。
 では少し早いですが早速この機能を使って絵をキーボードで上下左右に自在に操るプログラムを示し
たいと思います。

#include "DxLib.h" // WinMain関数 int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { int x , y ; // DXライブラリ初期化処理 if( DxLib_Init() == -1 ) return -1; // 描画先画面を裏画面にする SetDrawScreen( DX_SCREEN_BACK ) ; x = 0 ; y = 0 ; while( 1 ) { // 画面に描かれているものをすべて消す ClearDrawScreen() ; // 上下左右のキー入力に対応して x, y の座標値を変更する if( CheckHitKey( KEY_INPUT_LEFT ) == 1 ) x -= 8 ; if( CheckHitKey( KEY_INPUT_RIGHT ) == 1 ) x += 8 ; if( CheckHitKey( KEY_INPUT_UP ) == 1 ) y -= 8 ; if( CheckHitKey( KEY_INPUT_DOWN ) == 1 ) y += 8 ; // x , y が示す画面座標にBMP画像 test1.bmp を描画する LoadGraphScreen( x , y , "test1.bmp" , TRUE ) ; // 裏画面の内容を表画面に反映させる ScreenFlip() ; // 待たないと処理が早すぎるのでここで20ミリ秒待つ WaitTimer( 20 ) ; // Windows システムからくる情報を処理する if( ProcessMessage() == -1 ) break ; // ESCキーが押されたらループから抜ける if( CheckHitKey( KEY_INPUT_ESCAPE ) == 1 ) break ; } // DXライブラリ使用の終了処理 DxLib_End() ; // ソフトの終了 return 0 ; }
<実行例>

 実行画面は全く変わらないので以前のを流用します。(^^;
 このプログラムを実行するとキーボードの方法キーで自在にグラフィックを操作する事が出来ると
思います。
 では早速このプログラムの解説に入ります。

 色違いの最初、x = 0 ; y = 0 ; ですが、お気付きかと思いますが、この xy という変数
LoadGraphScreen 関数で絵を表示する時の座標指定に使われているところからわかるように、ずばり
絵を表示する位置』を示す変数です。
 変数 x の値が増えれば増えるほど絵は右のほうに表示され、変数 y の値が減れば減るほど絵は上の
方に表示
されるという仕組みです。そうです、この2つの変数の値を変更する事によって絵を表示する
位置を操作できると言うわけです。この仕組みから見てわかるように、2Dゲームでキャラクターの
存在位置はこのように xy の2つの変数を使って記憶しておくのが一般的です。
 なお見ての通り、最初は xyを代入して、絵は画面左上に表示されるようにしています。


 次に while( 1 ) を説明したいと思います。これは条件無しで無限ループをする事を
示しています。
 なぜ while( 1 )無限ループになるのか?ちょっと道をそれて説明します。
 while 文() 内の条件演算式であれば、つまり成立すればループを続けであれば、つまり
成立していなければループから抜ける、という仕組みである事は皆さんご存知かと思います。
 ですが while 文では実は条件式が成立しているかいないかなどは特に気にしていません。実際の
ところは while 文の () 内の演算結果が0以外だったらループを続け、0だったらループから抜ける
という単純な処理しかしていません。
 じゃあ一体 () 内で行われている条件式は一体なんなんだ、と思われるかと思います。
 ではここで一つ問題、次の式で変数 b には一体なんの値が代入されるでしょうか。

b = 100 > 10 ;

 答えは、では次の式では b に何の値が代入されるでしょうか。

b = 10 != 10 ;

 答えは、おわかりいただけたでしょうか? とどのつまり条件演算子である ==><=!= 等は
すべて条件が成立すれば演算の結果としてが、成立しなければ0演算の結果となるようになっているの
です。ですから while 文では演算結果であったかであったかは計算式などは見なくても、結果が
0以外かで判断すれば事は足りてしまうのです。( 実は if 文や for 文のループ条件部も同じ仕組みです )
 そして while無限ループをしたいときはこの単純な仕組みを逆手に取ります。
 用は while() 内の演算結果が0以外ならばループは続行されるので、while( 1 ) とすれば演算結果は
常に0以外(演算はしていませんが…)になるので、半永久的にそのループは繰り返される事になるのです。
以上、無限ループの仕組みでした。

 さて次になぜその無限ループを行う必要があるかをお話します。
 前々回、絵を動いているようにみせるには『少しずらして表示、少しずらして表示を繰り返す』といいました。
ですから for 文で『少しずらして表示』を繰り返したわけですが、今回は別に『少し動かして表示』回数を
制限する必要はありません
。ですので無限ループとなっているのです。

 次に今回の本題のキー入力部分です。
 といってもたいしたことはしていません。要は『→』キーを押していたら絵が右に、『↓』キーを押していたら
絵が下
に動けば良いわけです。先程説明した通り、今回、絵を表示する座標は xy という変数を使って操作
しているので『→』を押していたら x の値を少し増やしてやり、『↓』を押していたら y の値を少し増やして
やれば
いいのです。
 押しているかどうかを判断するには CheckHitKey 関数に押しているか調べたいキーのマクロを渡して、関数
から返ってくる値を調べれば言いので結果的に

例 『→』キーを押してたら変数 x に8の値を加算する

if( CheckHitKey( KEY_INPUT_RIGHT ) == 1 ) x += 8 ;

 と言うような記述になるのです。プログラムにはこのような記述が4行あるのは上下左右すべての方向キーをチェックするからです。


 最後に if( ProcessMessage() == -1 ) break ; と if( CheckHitKey( KEY_INPUT_ESCAPE ) == 1 ) break ; です。
 if( CheckHitKey( KEY_INPUT_ESCAPE ) == 1 ) break ; は見ての通りエスケープキーが押されていたら break 文で
while ループを抜ける事を示しています。これは問題ないと思います。
 それはさておき if( ProcessMessage() == -1 ) break ;ProcessMessage ってなに!?と思われた事と思います。
 この関数はDXライブラリが Windows というマルチタスクOS上で動作するために必要不可欠な関数です。
 要は本来 Windows というOSは沢山のソフトが一度に動作し、それぞれのソフトは協調して Windows上 に存在する
ために Windowsシステムから色々な指令や情報が各ソフトに送られてきます。(『マウスが移動した』『ウインドウを
閉じなさい』など)一般的な Windows ソフトはその指令や情報によって動作を分岐・決定し、処理をします。
 つまり Windows では各ソフトはシステムから送られてくる指令や情報常に監視し、それらの情報が届いたら直ちに
送られてきた指令・情報を処理しなくてはならないのです。
 ですがDXライブラリではそんな面倒くさく、ゲームには全く関係ない作業はDXライブラリ内でどうにかしてしまおうと思い、
それらの情報を勝手に処理する関数を用意しました。それが ProcessMessage という関数なのです。
 ProcessMessage 関数はなんの引数も取らず、ただただ実行するだけです、後は勝手に Windows システムから送られ
てくる情報を処理してくれます。そして処理が終ると返ってきます。
注意しなくてはならないのは、ProcessMessage 関数の戻り値です。正常に情報処理が終了した場合は が返って
きますが、情報処理に異常が発生した場合は -1 が返ってきます。この場合はなるべく早くソフトを終了しなくては
なりません。

 さてこのプログラムではどうしているかと言うと。
if( ProcessMessage() == -1 ) break ;

 つまり ProcessMessage 関数で異常が起きたら while無限ループから脱出するようにしています。

 ところで本来常に監視しておかなければならない Windows システムからの指令・情報ですが、実際にはそんなにずっと
監視している必要はありません。ですから今までは ProcessMessage 関数は使わなかったのです。
 ですが今回のように、手を加えなければ永遠にループし続けるようなプログラムの場合は、ループのどこかに ProcessMessage 関数を
一つ入れるくらいはする必要があります。これは重要な事ですので覚えておいてください。

 長々と書いてしまいましたが、今回はこの辺で終りです。
 次は絵の表示速度を劇的に速くする方法を紹介したいと思います。

 なお前回の最後に、『ジョイパッドとキーボードで操作出来るように』と言っていましたが、ジョイパッドで
操作できるようにするのは別の機会にしたいと思います。

戻る