HOME > ActionScript > テトリスアルゴリズム > テトリミノを固定する

テトリミノを固定する

積みあげる

フィールド上に出現したテトリミノをフィールド上に固定する機能を追加します。
この機能が追加されると「積みあがっていく」ようになるので、やっと少しゲームっぽい感じになります。

ソースファイル pt6.zip

大筋ではありますが、今回固定処理の動作が加わる事で次の様なプロセスが繰り返されるようにします。

  1. 落下中のテトリミノが下方向にぶつかる
  2. 固定コードをフィールドデータに入れる
  3. 新しいテトリミノのパターンデータを用意してフィールドデータに反映
  4. フィールドの再描画

定義

最初の「フィールドを描画する」の時に幾つか用語や仕様を定義しましたが、固定する処理を実装して行くにあたり、仕様を一つ追加します。

「固定後のテトリミノもガイドライン通りの7色で色分けする」

なんて事のない決めごとなのですが、ロジックにすると結構変わってくるので、この後の説明のつじつまや根拠を明確にする為に決めておきます。

フィールド上に固定した後は固定用のカラーで統一してしまう仕様のテトリスも多いので、好みで決めてしまって良い事項ではありますが、私がここまで記述してきたロジックは基本的に色分けする事を前提に進めています。
とは言え少しの変更で「単色」で処理する事も出来るようになります。
最初から「単色」を前提で作成していると後から「色分け」に変更するのはちょっと手間ですが、「色分け」の仕様で作成しておけば「単色」の仕様にも対応するのは容易です。

基本仕様 テトリミノはガイドライン通り4つのセルで一つを形成し、7種類存在。
テトリミノの色、出現時の向きはガイドラインに準拠。
固定フィールドの幅は10セル、高さは20セル。壁及び固定フィールド分の幅と高さを含めた、フィールドの完全サイズは幅12セル、高さ23セル。今回このサイズは固定で変動なし。
テトリミノの出現位置は固定フィールドの上。
テトリミノの出現位置に固定されたテトリミノが存在した場合ゲームオーバー。
固定後のテトリミノもガイドライン通りの7色で色分けする。
操作系 アローキー上で右回転。
アローキー左右で横移動。
アローキー下で落下速度アップ。

考えておく事

フィールドにテトリミノを固定するとはどういう事か簡単に触れておきます。
おそらく前回までの内容を理解されていると想像が付くと思いますが、落下中のテトリミノが下方向に何かにぶつかった(衝突判定で真が返る)時に、落下中のテトリミノが存在しているその位置(フィールドデータ配列の要素)に「固定」を表すコードを入れておきます。
あとは固定コードを反映したフィールドデータを基にフィールドを描画するだけです。

色分けする必要がある為、実際には「固定コードを入れておくだけ」とはいきませんが、ニュアンスとしてはそんなプロセスなんだと言う感じに捉えた方がわかりやすいです。
固定コードは「FIXED」という定数を用意して、値は「10」とします。

Private const FIXED:uint = 10;

次にテトリミノを固定した後は新しいテトリミノをフィールドに用意する必要がありますので、今回は固定処理の実装と一緒に「新しいテトリミノをフィールドに用意する」メソッドも追加します。
これはゲーム中で「小さな起点」となる処理なので意外と重要なメソッドになります。

それ以外は、前回までに記述した処理をところどころ少し変更を加えますが、大きな追加や変更はありません。

フィールドデータの更新

固定のタイミング

テトリミノが固定されるのは下方向に対して何かにぶつかった時ですので、フィールドデータに固定コードを入れるタイミングも下方向に対して衝突が検出出来た時になります。
具体的にはtetriminoControl()関数の「下」に対する分岐(main.asファイル 332行目)の中で固定の為の処理を実行します。

固定の実行

固定を実行する処理(フィールドデータに固定コードを方法)ですが、これはフィールドにテトリミノのパターンデータを入れたり削除したりする処理担当のfieldMapping()関数で行います(main.asファイル 531行目)。
つまるところ、フィールドデータの更新処理は全てこのfieldMapping()関数で行う事になります。
第一回目からその説明をしても良かったのですが、ポイントを絞ってコンパクトな処理から説明した方が理解しやすいので、少しずつ拡張しながら説明しました。

では今回の固定処理の為にfieldMapping()関数をまた少し変更します。
ここまででfieldMapping()関数は以下の処理を行う事になりました。

  • フィールドデータに、落下中のテトリミノパターンデータを反映する。
  • フィールドデータか、ら落下中のテトリミノパターンデータを削除する。
  • フィールドデータに、落下中のテトリミノパターンデータを固定する。

fieldMapping()関数にフィールドデータの更新を要求する際、それが上記三つの内のどの処理の要求なのかがわかるようにしてあげる必要があります。これは引数でその指示コードを渡してあげるように変更します。単純に0~2の番号を渡して、それによって処理を分岐するだけです。

固定コードの入れ方

フィールドデータに固定コードを入れておく上で重要なのは、「後から色分けできるように値を入れておく」事です。単に固定コードのFIXEDの値を入れただけでは、あとからそれがどのテトリミノパターンを固定したものなのかの識別ができない為、色分けする事も出来なくなってしまいます。
なのでフィールドデータに固定コードを入れる場合はこのFIXEDの値をそのまま入れるのではなく「テトリミノコード + FIXED」とした値を入れておきます(main.asファイル 554行目)。

fieldData[y][x] = テトリミノコード + FIXED;

フィールドを描画する時にはこれを次の様に復元します(main.asファイル 582行目)。

テトリミノコード -= FIXED

また、衝突判定を行う時の評価では前回まではフィールドデータ中に壁コードを検出していましたが、今回からはFIXEDコードの値より大きい値を検出するように変更します(main.asファイル 442行目など)。

if (fieldData[y][x] == WALL) // 前回まで

if (fieldData[y][x] > FIXED) // 今回から

何故そのまま入れておかないのか

ここで何故フィールドデータに入れる固定コードとして「FIXED + テトリミノコード」とするのかを簡単に説明しておきます。固定後のテトリミノを描画する際に、固定されているテトリミノの色を特定する必要がある為、テトリミノパターンを特定できる値の形で入れておく必要がある事は前述で説明しました。

では単純にそのままテトリミノコードを入れておけば良いのでは?というような気もします。
ところが固定コードとしてテトリミノコードをそのままフィールドデータに入れておくと、衝突判定の評価で「EMPTY(0)より大きい値を検出したら衝突」と言うような評価を取らざる負えなくなります。

if (fieldData[y][x] > EMPTY) // 空白以外は衝突

それはそれでまた問題なさそうな気がしますが、この評価で衝突判定を取ろうとすると落下中のテトリミノのコードも引っかかってしまうのです。

つまり落下中のテトリミノは周りに対する衝突判定を実行している段階で、フィールドデータ上にある自分自身のテトリミノコードにも衝突の判定を検出してしまい、場合によっては移動できなくなってしまいます。
その為、「落下中のテトリミノコード」か「固定されたテトリミノコード」かを区別できるようにしておく必要があるわけです。

ただ、ここまで書いている私のロジックだとそうなってしまうという事で、そうならない様なロジックで再現する事も可能です。

新しいテトリミノを用意する

フィールドデータにテトリミノを固定した後は、フィールドを描画する前に新しいテトリミノを用意して、そのデータもフィールドデータに反映しておきます。

この処理の為に追加したメソッドはsetTetromino()メソッドです(main.asファイル 235行目)。
やっている事は単純で、ランダム値を選んで次のテトリミノパターンデータを選出、初期配置位置でフィールドデータに反映というところまでです。
今のところはここまでですが、このメソッドには後々「次のテトリミノ」の処理や、ランダム値の偏りを出来るだけ均一化する処理とも連動させていきます。

また、注意点としては呼び出し元から受け取ったデータの扱い方です。
基本的には引数で「落下中のテトリミノパターンデータを保存しておく変数」の参照を受け取り、その参照先を新しいテトリミノパターンデータで更新していますが、この「参照」の取り扱いを間違うと、新しいパターンデータが全く反映されなくなってしまします。
参照などの詳細についてはテトリスのアルゴリズムとは関係ありませんのでここでは触れませんが、もし知識が曖昧になっているようでしたら、割と重要な概念ですのできちんと理解しておく事をお勧めします。

って、私自身がActionScriptもCのポインタと同じ理屈でしょくらいの大雑把な理解度ですみません。

動作確認

テトリミノが動かない時はFlash画面上を一度クリックしてみてください。

今回から上部の壁の形状を少し変えました。前回までのままでも処理できるのですが楽しました。
まだラインが揃っても消えませんのでゲームとしては成り立ちませんが、積み上げられるようになると少しはゲームっぽいので気分が違います。ゲームオーバー判定のシステム部分も入れてないので、出現エリアにもこもこ重なったりします。

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

Adobe Flash Playerのダウンロード

ソースファイルについて

ソースファイルはasファイルのみです。

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

TOP