C++でつくったテトリスの完成品

前回の鳩ではなく猫並みの知能を手に入れるためにC++でアプリをつくるで宣言したとおり、C++でテトリスをつくります。まずは本体部分のソースファイルの内容を示します。無精をしてall.hのなかにinclude文とdefine文やグローバル変数を書いています。

WinMain関数

WinMain関数を示します。

app.cpp

ヘッダーファイルについて

all.hは以下のようになっています。

タイマーを3つ使います。IDがTIMER_FREE_FALLのタイマーは1秒経過するごとにテトリミノをひとつ下げるためのものです。TIMER_SOFT_DROPは↓ボタンを押しているあいだテトリミノを急速落下させるためのタイマーのIDで、TIMER_DROP_LINESは横一列にブロックを消すときにいきなり上のブロックが落ちてくるのではなく間を空ける(特に意味はない。ちょっとした演出)ためのものです。

all.h

基本は前回と同じ?

MainWindow.hとMainWindow.cppは前回のコードにちょっとだけ追加しただけです。タイマーを使うのとキーの押下に反応するようにしました。

MainWindow.h

MainWindow.cppを示します。Create関数は表示するウィンドウのサイズが変更されています。OnDestroy関数は前回と同じです。WM_KEYDOWN、WM_KEYUP、WM_TIMERメッセージを処理するためにWndProc関数を変更しています。OnCreate関数のなかでゲームの初期化のような処理をしています。OnPaint関数も描画したいものが前回とは違っているので変更になります。それからそれっぽいイメージを出すために背景を黒にしています。これだけでなんとなくスタイリッシュなアプリっぽく見えます。

前回とほぼ同じ部分だけ先に示します。

MainWindow.cpp

ここから前回とは違ってきます。

WndProc関数とその周辺

MainWindow.cpp

OnCreate関数

ウィンドウが生成されたらウィンドウハンドルが確定するのでこれをグローバル変数に格納しています。そしてタイマーをセットします。IDがTIMER_FREE_FALLのタイマーは1秒経過するごとにテトリミノをひとつ下に下げるためのものです。もうひとつのTIMER_SOFT_DROPは

MainWindow.cpp

OnDestroy関数は前回と同じです。

OnKeyDown関数

OnKeyDown関数はキーが押されたときの処理をおこないます。Tetrisクラスのメンバー関数を呼び出してテトリミノを移動させる処理(←キーが押されたらMoveLeft関数を呼び出してテトリミノを左に移動させるなど)をおこないます。

↓キーが押されているときはm_IsSoftDropフラグをTRUEにして、キーが押されている間高速落下させます。ソフトドロップという名前なのに高速落下なの?と思うかもしれませんが、ハードドロップの場合は一瞬で下まで落ちます。ハードドロップと比較すればソフトかも?

最後に再描画の処理をしています。その前にGetRect関数を実行していますが、これはInvalidateRect関数の第二引数をNULLにして全体を再描画しようとすると急速でテトリミノを移動させるときに画面がチカチカするので、再描画の範囲を限定するために使っています。とりあえず落下中のテトロミノとその周辺を再描画し、それ以外に必要なときはそのときでInvalidateRect関数を呼びます。

OnKeyUp関数

↓キーが離されたときにはm_IsSoftDropフラグをクリアするためにOnKeyUp関数内で処理をします。

描画処理

描画処理はTetrisクラスのDraw関数を呼び出しておこないます。

タイマーの処理

タイマーがセットされているときはOnTimer関数が呼び出されます。どのタイマーからのメッセージなのかを判断(WPARAMでわかる)してテトリミノを下に移動させたり消えたラインを詰める処理をしています。

TetriminoPositionクラスとBlockクラス

描画処理をおこなう場合、どこに何色で描画するかを知る必要があります。これはBlock.hで定義されています。メンバ関数はないのでBlock.cppはありません。

TetriminoPositionクラスとBlockクラスの違いですが、落下中のテトロミノを構成するブロックの位置はTetriminoPositionクラスを使い、着地して固定されたブロックはBlockクラスで管理します。

Block.h

Block.h

まだ肝心のTetrisクラスについてなにも説明できていませんが長くなるので(本当に長い……)次回にします。