JavaScriptでミスタードリラーもどきを作る(2)の続きです。今回はブロックを落下させる処理を実装します。

ブロックの落下処理

ブロックが破壊されることで落下を開始するブロックがある場合は落下処理をおこないます。カプセル以外のブロックは支えがなくなるとグラグラ振動し、しばらくすると落下を開始ます。

そこでまず「支えがないブロック」を取得します。その取得方法ですが、幅優先探索で取得します。

一番下の行にある破壊されていないブロックを起点とする
上に破壊されていないし落下を開始していないブロックがあるならたどっていく
上下左右に破壊されていないし落下を開始していない同色のブロックがあるならたどっていく
(ただしエアカプセルはくっつかないので下・左・右にはたどらない)
たどりつくことができなかったブロックは支えがないブロックである

支えがないブロックを取得したら落下待機状態にします。ただしエアカプセルはただちに落下させます。ただし、
エアカプセルであっても下にブロックがある場合はただちに落下することができないので待機状態にします。

それぞれをグループ化したらFallingGroupのインスタンスを生成して配列に格納します。またエアカプセルは横のつながりを持たないのでグループ化するときは単体で扱います。

ブロックの更新

ブロックの更新処理は以下のようになります。

fallingGroupが存在する場合はWaitCountを減らす
WaitCountが0以下なら落下させる
(落下し終わると自動的にFallingGroup.IsDead == true になる)
落下が完了した場合は他のブロックとくっつくものと引き続き落下するものにわける
引き続き落下する場合は待機時間なしで次の落下処理を開始する
くっつくものは同色で4つ以上くっついている場合、消滅させる
消滅した場合、新たな支えがないブロックが発生するので setBlocksTofallingGroups(getNoSupportBlocks()) を実行する

あたり判定

あたり判定(プレイヤーの死亡判定)は以下のようにおこないます。

すでにプレイヤー死亡の場合はなにもしない
エアカプセル以外の破壊されていないブロックがプレイヤーと同じ位置に存在する場合、プレイヤーと同じX座標でY座標の差がBLOCK_SIZE / 8未満の位置に存在する場合はプレイヤー死亡とする
プレイヤーがいる位置にカプセルがある場合はカプセル回収の処理をおこなう

カプセルを回収時の処理

カプセルを回収したときの処理を示します。

エアカプセルの死亡フラグのセット
カプセルが破壊されることで支えがないブロックが発生するかもしれないので setBlocksTofallingGroups(getNoSupportBlocks()) を実行する
エアの回復(最大値を超えない範囲で最大値の10%分)
スコアの加算
爆発の火花の発生
効果音の再生

プレイヤー死亡時の処理

プレイヤー死亡時は以下の処理をおこないます。

死亡フラグのセット
残機 1 減らす
効果音の再生
爆発の火花の発生
自機がまだ存在する場合はプレイヤーを復活させる
存在しない場合はゲームオーバー処理

プレイヤーを復活させる処理を示します。

プレイヤーがいる位置から上にあるブロックは必要ないので対応するblocks2x2[row][col]にnullを代入しています。またそれよりも下の部分は残すのですが、落下中のブロックが宙ぶらりんの状態で浮いてしまうので落下状態と待機状態をいずれも解除して落下処理前の位置に再設定しています。

そのあと死亡位置の中央でプレイヤーを復活させます。

ゲームオーバー時とステージクリア時の処理

ゲームオーバー時は以下の処理をおこないます。

効果音の再生とBGMの停止
スマホ用の操作ボタンの非表示
ゲームスタートボタンの再表示
press◯◯Keyフラグのクリア

地味に重要なのがプレイヤーを移動させるためのpress◯◯Keyフラグのクリアです。スマホでプレイしていてゲームオーバーになった場合、これにともなって操作用ボタンが消えてしまうのでこれらのフラグはユーザーの操作ではクリアされなくなるのです(PCからの操作であれば問題ない)。

ステージクリア時の処理を示します。

移動不可、あたり判定無効にしたいので死んではないけど死亡フラグをセットする
BGMの停止と効果音の再生
落下中のブロックに関する情報のクリア
ステージクリアを示す文字列の表示
次のステージのブロックの生成
プレイヤーの位置の初期化
停止していたBGMの再生

ステージクリアを示す文字列(DOM要素を使う)を下から上へ移動するように表示させます。

描画処理

描画処理を示します。

canvas全体を黒で塗りつぶす
ブロックを描画する
ゴールが見える位置にあるときは描画する
火花があるときは描画する
プレイヤーが生存するときは描画する
上部にスコア等を描画する