以前テトリスを作成しましたが、PictureBoxを使用しています。今回はPictureBoxを使わずにつくります。

主な仕様

落下中のテトリミノはMovingTetriminoクラスで、着地し固定されたテトリミノはFixedTetriminoクラスで扱います。どちらも静的クラスです。

次のミノは3つまで表示されます。また落下中のミノはホールドすることができます。

スーパーローテーションシステム対応です。Tスピントリプルも可能です。

BGMをつけました。

まずデザイナですが、メニューバー以外ありません。

MovingTetriminoクラスが長くなったので、次回示します。ここではそれ以外のクラスを示します。

まず使用する定数に関するクラスを示します。

次にBlockクラスを示します。これは描画するブロックを管理するためのクラスです。

TetriminoTypesはテトリミノのタイプを示す列挙型です。

TetriminoAngleはテトリミノが向いている方向を示す列挙型です。

ではForm1クラスをみてみましょう。

最初にコンストラクタ内の処理を示します。

タイマーイベントを使用するのでイベントハンドラ Timer_Tickを追加しています。またMovingTetriminoクラスとFixedTetriminoクラスのイベントに対応できるようにしています。

MovingTetrimino.TetriminoFixedはミノが設置したときのイベントでMovingTetrimino.CantPutNewTetriminoは積み重なったミノが最上位まで到達してこれ以上積めなくなったときに発生します。FixedTetrimino.LinesDeletingイベントとFixedTetrimino.LinesDeletedは横一列がそろって消去されるときに発生します。すぐに消えるのではなくちょっとだけタイマーをとめます。

CreateOutsideBlocksメソッドは外枠のブロックを描画するときに必要なブロックの位置を求めるためのものです。

ゲームスタート以降の処理を示します。

ゲームスタートにおける処理は、

(1) FixedTetriminoクラス内のブロックオブジェクトを削除
(2) 一番最初に落ちてくるミノの取得

です。

isGameOveredフラグがクリアされ、キー操作が可能になります。ホールドされているミノがあればクリアして、得点も0にリセットします。そしてタイマーをスタートさせます。

キー操作とタイマーイベントに関する処理を示します。

ミノが一番下に落ちてもすぐにその場に固定されるわけではありません。ロックダウンには0.5秒間の猶予があり、キー操作によってその時間はリセットされます。ただしこれは何回でもできるわけでなく15回までです。ミノが一段下がればこの15回はリセットされます。

↓キーがおされると押している間、ミノは下に落ち続けます。またスペースキーを押すと瞬時に下に落ちて固定されます。

ミノを左右に移動させたりドロップさせる動作はMovingTetriminoクラスでおこないます。

MovingTetrimino.TetriminoFixedイベントが発生したときの処理を示します。ここでやっていることはホールドを可能にすることと(いったんホールドしてしまうと交換したミノをセットするまで次のホールドができない)と、ドロップポイントを加算することです。

ライン消去時の処理を示します。ここではタイマーを一時的に停止(横一列に揃ったブロックが消え、他のブロックが浮かんでいるように見せる)するとともに、得点を追加しています。

ホールドの処理です。ホールドされているミノがあるときはそれと入れ替え、ない場合は落下中のミノをホールドして次のミノを降らせます。

MovingTetrimino.PopNext()は次のミノを取り出し、現在のミノにセットします。MovingTetrimino.Typeがセットされると自動的に最上段からおちてくるようになっています(後述)。

ポーズ時の処理です。Escキーが押されるとポーズになります。ポーズのときはタイマーを停止させます。ポーズのときにEscキーを押すとポーズが解除されます。

ゲームオーバー判定の処理です。MovingTetrimino.CantPutNewTetriminoイベントが発生したらゲームオーバー処理を行ないます。タイマーを停止させてisGameOveredフラグをセットします。

描画に関する処理です。MovingTetrimino.Draw(Graphics g)メソッド、FixedTetrimino.Draw(Graphics g)メソッド、MovingTetrimino.DrawGohst(Graphics g)メソッドを呼び出してミノを描画させます。

また次回3回分のミノの種類を取得してShowNextTetoros(Graphics g)メソッドでフィールドの右側に描画します。ホールドされているミノや現在の得点を表示するとともに、現在ゲームオーバーやポーズ状態であるならそのように表示させます。

起動直後はisGameOveredフラグがtrueなので「GameOver」と表示されるのですが、一度もゲームをしていないのに起動直後に「GameOver」と表示されるのはおかしいです。そこで起動直後はfirstGameフラグの効果で「GameOver」と表示されないようにしています。

フィールド上に固定されているミノを管理するためのFixedTetriminoクラスを示します。

Init()メソッドは初期化のためのものであり、フィールド変数 List<Block> Blocksをクリアするためのものです。

ExistsBlock(List<Block> blocks)メソッドはわたされたブロックのリストの座標に固定されたミノが存在するかどうかを返します。

DeleteLines()メソッドは横一列にブロックが並んでいるか調べて並んでいる場合はその行のブロックを消去し、LinesDeletingイベントと LinesDeletedイベントを発生させます。

イベントハンドラ LinesDeletedHandlerに渡される引数 LinesDeletedArgs を示します。消されるラインの数を送るときに使います。