文系人間がプログラミングをはじめてみた。

プログラミング初心者のゼロからの勉強記録。

VBAテトリス 詳細編 ゲームオーバーの判定・演出

どうもこんにちは。

 

今日も今日とて、マクロで作ったテトリスの解説をしていきます。

 

どんな感じのものなのかイメージを確認したい方は以下リンクからどうぞ。

programminghajimetemita.hatenablog.com

 

今回の内容はゲームオーバーの判定・演出についてです。

 

 

1.テトリスの挙動

まずはいつも通りテトリスの挙動を考えてみましょう。

テトリスではどのような状態になるとゲームオーバーと判定されるかというと、

ブロックを動かすことができなくなった状態になったときです。

 

もう少し具体的にいうと、初期表示される位置がブロックで埋まってしまった状態です。

このような状態になると、次のテトリミノを表示しようにもできませんから、

ゲームが続行できないのでゲームオーバーということですね。

 

で、ゲームオーバーと判定されると、以下の演出が行われます。

(なお、これはテトリスミニの挙動です)

 

・下の行から一行目まで、一行ずつブロックの揃った行が表示されていく

・上の演出によりゲーム画面全体がブロックで埋まった後、

一行目から最下行まで、一行ずつブロックの揃った行が消えていく

 

言葉だけではわかりづらいと思いますので以下にイメージを載せておきます。

(これでもわかりづらいかもしれませんが。。。)

 

まず、下から一行ずつブロックの揃った行が表示されていきます。

一行目に到達後は一行目から順にブロックの揃った行が消えていきます。

最後はすべてのブロックが消えた状態になります。

 

テトリスの挙動の解説は以上になります。

次はこれを踏まえてどういった処理が必要になるかを考えます。

 

2.必要な処理

まずはゲームオーバーの判定です。

先ほど述べた通り、

初期表示される位置にブロックが埋まっている状態

がゲームオーバーの条件になります。

 

初期表示位置にブロックがあるわけですから、

ゲーム画面一行目の状態が、

□□□■■■■□□□

例えばこんな状態になっているとき、ゲームオーバーと判定できればよいですね。

(□は空白のマスと考えてください)

 

「こんな状態」ではコード化が難しいのでこれを言語化しますと、

「一行目のセル範囲の背景色に無色と黒色が混在している状態」と言い表すことができます。

(なお、これは私の解釈であり、他の解釈もあり得ると思います。

唯一の解ではないという点ご留意ください)

 

この無色と黒色が混在したセル範囲について、

ColorIndexがどうなるかというと、「Null」になります。

 

ということで、これを利用して、

一行目のColorIndexが「Null」であるとき、ゲームオーバーと判定する、

という処理ができれば、テトリスの挙動を再現することができます。

 

ちなみに、この判定はブロックが壁やほかのブロックに接地した時点で行われるので、

ゲーム続行可能なときは常に一行目が空白(無色)になり、

ColorIndexが「Null」にならないので、上記判定でイメージ通り動作させることができます。

 

次に、ゲームオーバーの演出です。

まずは下から一行ずつブロックの揃った行にしていけばよいので、

繰り返し処理を使ってブロックの揃った行にする処理を繰り返せばOKですね。

なお、ブロックの揃った行にするのはセルの書式を調整すればよいです。

 

上からブロックの揃った行を消していく演出についても、

上記と同様に、「行の消去(=セルの書式調整)を繰り返す」ことでOKです。

 

以上、必要な処理について解説しました。

最後にコードの内容に入りましょう。

 

3.ゲームオーバーの判定・演出を行うコード

まずはゲームオーバーの判定に関するコードです。

必要な処理で述べた通り、

一行目のColorIndexが「Null」になったらゲームオーバーと判定したいので、

その状態になったときに「True」を返す関数を作りました。

 

Function checkgame() As Boolean
    If IsNull(Range(Cells(start_r, leftedge_c), Cells(start_r, rightedge_c)).Interior.ColorIndex) Then
        checkgame = True
    End If
End Function

 

IsNull()の部分で、カッコ内に記述した内容がNullかどうかを判定しています。

繰り返しになりますが、Nullと判定されれば「True」を返す仕組みになっています。

 

次にゲームオーバーの演出のコードです。

必要な処理は「セルの書式調整」+「繰り返し」ですので以下のようになります。

 

   Sub gameover()
    For r = end_r To start_r Step -1
        With Range(Cells(r, leftedge_c), Cells(r, rightedge_c))
            .Interior.ColorIndex = 1
            .Borders.LineStyle = xlDouble
            .Borders.ColorIndex = 2
        End With
        Application.Wait [Now() + TimeValue("00:00:00.2")]
    Next r
    For r = start_r To end_r
        Range(Cells(r, leftedge_c), Cells(r, rightedge_c)).ClearFormats
        Application.Wait [Now() + TimeValue("00:00:00.3")]
    Next r
End Sub

 

上側のForがブロックの揃った行の表示、

下側のForがブロックの揃った行の消去のコードになります。

 

上側のコードでWithの中に記載しているのが、

ブロックの書式になります。

繰り返し処理は下の行から上の行に向かって行いたいので、

カウンタ変数の設定を「最下行 To 一行目 Step -1」としています。

 

下側のコードはブロックの消去に関するコードですが、

単純にClearFormatsで書式のクリアを行うことで再現しています。

 

なお、いずれのコードでもApplication.Waitというコード(指定秒数処理中断する)

を使っていますが、

これは演出がきれいに見えるようにするためです。

処理中断時間を設けないと、テトリスミニの挙動っぽくならなかったので、

実際の動きと見比べつつ、中断時間を調整しました。

 

以上、判定と演出のそれぞれのコードについて解説しました。

これらを組み合わせると以下のようなコードになります。

 

        If checkgame = True Then
            Application.ScreenUpdating = True
            Application.Calculation = xlCalculationAutomatic
            Call gameover
            Exit Do
        Else
            ・・・
        End If

 

checkgameがTrue、すなわち、

ゲーム画面一行目の一部にブロックが埋まれば(ColorIndex=Null)、

Then以下のコードが実行されます。

 

Then以下のコードではgameoverを呼び出しているので、

当該マクロの実行によりゲームオーバーの演出が流れます。

 

なお、この処理は、

テトリミノが初期位置に表示される⇒接地するまで下に落ちるの繰り返し処理

の中に組み込まれています。

そして、ゲームオーバーであるということは、

その繰り返し処理を終了する必要がありますので、

gameoverの呼び出し後、Exit Doにより繰り返し処理を終了させています。

 

以上でゲームオーバーの判定・演出の処理のコード解説を終わります。

 

4.おわりに

今回はゲームオーバーの判定・演出について解説しました。

今回紹介したコードをもってテトリスはほぼ完成です!

ゲームとして成り立つ内容になってます。

 

ただ、ゲーム中無音です。さみしいですね。

やっぱりBGMがあった方がゲームっぽいですよね。

 

ということで、次回はゲーム中に音楽を流すコードについて解説します。

 

ではまた。