HOME > ActionScript > テトリスアルゴリズム > テトリミノを動かす

テトリミノを動かす

テトリミノが動く理屈

今度はテトリミノを動かしてみます。使用するキーはアローキーの左右と下です。

ソースファイル pt3.zip

位置情報の保存

テトリミノを動かすとはつまりどういう事かと言うと、「テトリミノを表示してみる」のところで出てきた「テトリミノの位置情報」、これが動くと言う事になります。「動く」と言っていますが、具体的には「位置情報を保存している変数の値が、キー操作に合わせて更新される」です。
この位置情報の保存には「dropLocation」というグローバル変数を用意します。Object型で手作りしても良いですが、ActionScript3.0にはPoint型がありますので、これを使用します。

private var dropLocation:Point;

フィールドの再描画

位置情報を保存する事が出来るようになったら、後は位置情報が更新される度に新しい位置情報を基準にしてテトリミノのパターンデータをフィールドデータに反映し、フィールドを再描画するだけです。動かす為の基本的な考え方はこれだけです。

アタリ判定

動す理屈はそれだけなのですが、動かすとなるとアタリ判定の処理が必要になります。テトリスの場合のアタリ判定は「落下しているテトリミノ」を基準にして、「積み重なっているテトリミノ」と「壁」に対するアタリ判定の処理が必要になります(ゲームの仕様によってはその限りではありません)。ですがこれも考え方が判れば実はとても簡単です。とりあえず「壁」に対するアタリ判定の処理を実装してみます。

アタリ判定のプロセス

動かすとはつまり位置情報を更新するわけなのですが、処理のプロセスで考えると位置情報を更新するよりも先にアタリ判定を調べておく必要があります。調べて「位置情報を更新していいかどうか」を判断してから、動かしたい方向に位置情報を更新→再描画、何かがあって「動かせない」場合は位置情報を更新せず、再描画も行わないと言う処理に分岐します。

アタリ判定の考え方

ではアタリ判定の考え方です。
例えばテトリミノパターンデータ7のT字を右に動かす場合で考えてみます。キーが押されてまず最初に調べるのは今落下中のテトリミノのパターンデータ配列です。落下中のテトリミノのパターンデータはdropTetrominoというVector配列のグローバル変数を用意して、新しいテトリミノが現れるたびに保存します。

また、実際のstage上でのピクセル座標はx値×セルのサイズで算出します。

図5

private var dropLocation:Point;

アタリ判定の処理はこのパターンデータ配列の「コード」の入っている要素を探す事から始まります(実際には「0以外」という条件で探索する)。
その探索手順は「右へ移動できるかどうか」を調べたいので、二次元目の最後尾の要素から一列ずつ先頭に向かって走査を行います。イメージ的にはテトリミノパターンデータの右上から探索を開始して下へ向かい、これを左へ向かって列ごとに繰り返すという感じです。

そして走査しているとコードの入った要素にぶつかります。ぶつかったらそのコードを検出した要素の位置がフィールド上のどこに存在するのかを調べます。これは落下中のテトリミノのフィールド上の位置情報(dropLocation)に、検出した要素のパターンデータ配列でのインデックス値を足す事で算出できます。

フィールドデータの参照

そのフィールド上の座標まで検出出来たら後は簡単です。フィールドデータ上でその位置の「右隣」に何かあるかどうかを調べるだけです。今回の場合「壁」のコードが入っているかどうかを調べます。右隣の要素が「空白」だった場合は位置情報を更新、「壁」だった場合は何もせずに処理を終了する流れです。
この一連の処理はmain.asのは232~326行目に記述しています。

フィールドデータの更新

フィールドデータの更新の前にしなければならない重要な事があります。
今現在フィールドデータに反映されているテトリミノのパターンデータを削除しなければなりません。
削除せずに再描画をすると移動前のパターンデータの残骸部分にも再びテトリミノの描画が実行されてしまい、右の図の様な描画状態になってしまいます。

図5

削除の仕方はいたって簡単で、フィールドデータにテトリミノのパターンデータを反映する処理と同じです。違いはフィールドデータの要素に空白である「0」を入れるか、テトリミノコードを入れるかの違いだけで、行う事はまったく同じなのです。
なのでこの処理についてはfieldMapping()メソッドに少し手を加えるだけで終了です(main.as 333行目)。

重要なのは処理自体よりも「位置情報を新しく更新する前に削除を実行する」と言う事です。位置情報を更新した後ですと、フィールドデータのどの部分を削除(0を入れる)すれば良いかの情報が無くなってしまうからで、このプロセスの順序だけは注意が必要です。

動作確認

描画の処理は前回のフィールドを描画する処理とほぼ同じです。
フィールドを描画するためのdrawField()メソッド(main.asファイル 244行目)は、単にフィールドデータ配列の情報を素に描画を行うだけのメソッドですので、処理実行前にフィールド配列データの状態さえ適切に更新されていれば問題はおきません。

下の実行画面の「update」ボタンを押すたびに、新しいテトリミノが抽選されてフィールド上に表示されます。まだ動かすことはできませんが、今回の表示する考え方を理解できると動かす方法も想像がつくのではないでしょうか。
と言うことで次回はテトリミノを動かしてみます。

Flashファイルをご覧いただくためには、
アドビシステム株式会社のフラッシュプレーヤー(Flash Player)が必要です。
インストールされていない方は下のボタンから、最新版が無償で入手できます。

Adobe Flash Playerのダウンロード

それとmain.asファイルの記述の中で、キーイベントで呼び出されるリスナー関数(onKeyDownHandler())の処理の中にはキーイベントを検出して他の関数に処理を振り分けるコードしか記述していません(main.as 215行目)。処理的にはこのリスナー関数の振り分けの中にtetriminoControl()の処理を記述してしまっても良いように見えます。(main.as 232行目)

方針にもよりますが、出来るだけイベントを検出するリスナー関数と、実際の処理の部分とは明確に分けて書く方が拡張性があり処理の見通しが良いのです。
ただ、仕様や状況によって開発しやすい手法で構わないんじゃないかなとも思いますので、その辺りは深く考えないでおいて下さい。

ソースファイルについて

ソースファイルはasファイルのみです。
今回も前回の処理部分は幾つか変更しました。気になる場合は前回のソースと比較してみて下さい。

使用する環境としてはFlashIDE(動作確認はSC4のみ)を想定していますので。適当に用意したflaファイルに、ダウンロードしたソースファイルをドキュメントクラスとして適切に設定すれば問題無く動作します。
また、コーディングはFlashDevelopを使用して行っておりますので、プロジェクト内にファイルを適切に配置、もしくはクラスパスを設定するなどすればFlashDevelopだけでも問題なく動作します。Stageサイズは幅、高さともに500pxです。
申し訳ありませんが、ご質問等にはお答えできませんので、ご使用は環境に合わせて各自行ってください。

TOP