今回は、Unityで作った落ちゲーの作り方解説の二回目
ブロックの消滅判定について
◆Google Playに公開した落ちゲー
では、どのようにして判定してブロックを消しているかについて説明する
まずは、ブロックのデータ管理用に、画面内でのブロックの配置に合わせて
横 7 × 縦 10 の二次元の配列を作る
これに合わせて、ブロックを消す条件が成立した場合にフラグ(「1」)を設定する配列も用意しておく
後からブロックを消すフェーズに来た際には、この配列を参照してフラグが立っているものを消す
◆ブロックデータ管理用の配列のイメージ
Blockdata = new int[GyouSize, RetsuSize] {
{0,0,0,0,0,0,0 },
{0,0,0,0,0,0,0 },
{0,0,0,0,0,0,0 },
{0,0,0,0,0,0,0 },
{0,0,0,0,0,0,0 },
{0,0,0,0,0,0,0 },
{0,0,0,0,0,0,0 },
{0,0,0,0,0,0,0 },
{0,0,0,0,0,0,0 },
{0,0,0,0,0,0,0 },
};
Erasedata = new int[GyouSize, RetsuSize];
◆処理の流れ
ア ブロックが最下位置まで落下した時に、上記の配列にブロックの番号を書き込む
Blockdata[CurrentGO[i].GetComponent<NumberCtrl>().GetCurrentPosition().y, CurrentGO[i].GetComponent<NumberCtrl>().GetCurrentPosition().x]
= CurrentGO[i].GetComponent<NumberCtrl>().GetNumber();
ここだけのコードを見てもわかりづらいが、仕組みとしては、現在落下してきたブロックが最下位置に到達したときに、そのx,y座標を取得して配列のインデックスとして使用し、その位置にブロックの番号を書き込んでいるだけ
イ そして、書き込んだ後のブロックを消すための判定だが・・・
大まかな流れとしては
・基準は今落下してきて停止したブロックとする
・行方向(水平方向)に消去の条件のチェック
・列方向(垂直方向)に消去の条件のチェック
で今回の場合の消去の条件とは、落下して停止したブロックの隣接する左右、上下のブロックの数字を足し合わせてちょうど10になったら、その10を構成するブロックを消すというものとしている
ウ 行方向のチェック
コードは下の方に記載した通りだが、行っているのは
落下してきて停止したブロックから順番に左側のブロックのデータを参照していき、隣が「0」なら終了
足して10になれば、消去用のデータ配列に「1」を書き込むというのを一巡行い、さらに基準のブロックから一つ右のブロックを基準として再チェック・・・という形で右にブロックがある限り繰り返すというような処理をしている
◆イメージ
黄色が落下してきたブロック
左方向に数字を足していく、上記の場合は
0,0、1,0、2,0、3,0の位置のブロックは足すと10になるため、
消去用のデータ配列の該当位置には「1」がセットされる
さらに基準ブロックを0,4に移動して同じチェックを行う
右端まで繰り返す
void GyouCheckLeft(Vector2Int currentpos)
{
int offset = 1;
int CheckCounter = Blockdata[currentpos.y, currentpos.x];
//現在の位置をもとに左側に何回チェックをするかを設定
for (int i = 0; i < currentpos.x; i++)
{
//左の範囲内かを確認
if (currentpos.x - offset >= 0)
{
//左が0でない
if (Blockdata[currentpos.y, currentpos.x - offset] != 0)
{
int result = CheckCounter + Blockdata[currentpos.y, currentpos.x - offset];
//現在位置と左のオフセット位置の値を加算して、10なら終了
if (result == 10)
{
//消去データをセット
Erasedata[currentpos.y, currentpos.x] = 1;
IsDeleteBlock = true;
for (int r = 0; r < offset; r++)
{
Erasedata[currentpos.y, currentpos.x - r - 1] = 1;
}
break;
}
else if (result < 10)
{
//データを加算
CheckCounter = result;
//オフセットを加算
offset++;
}
}
//左が0の場合ループ終了
else
{
break;
}
}
else
{
//範囲外のためループ終了
break;
}
}
}
//下記の処理にて、上記の処理を右端まで繰り返しチェックしている
void GyouCheck(Vector2Int currentpos)
{
for (int i = 0; i < RetsuSize - currentpos.x; i++)
{
if (Blockdata[currentpos.y, currentpos.x + i] != 0)
GyouCheckLeft(new Vector2Int(currentpos.x + i, currentpos.y));
}
}
エ 列方向のチェック
行のチェックと同じようなイメージで、落下して停止したブロックの上方向にブロックのデータを確認している
コードは下記の通り
void RetsuCheck(Vector2Int currentpos)
{
int offset = 1;
int CheckCounter = Blockdata[currentpos.y, currentpos.x];
int count = 0;
for (int t = 0; t < GyouSize; t++)
{
count += Blockdata[t, currentpos.x];
}
//全部足して10より小さいなら処理を終了 無駄を省く
if (count < 10)
return;
//現在の位置をもとに下側に何回チェックをするかを設定
for (int i = 0; i < currentpos.y; i++)
{
//下の範囲内かを確認
if (currentpos.y - offset >= 0)
{
//下が0でない
if (Blockdata[currentpos.y - offset, currentpos.x] != 0)
{
int result = CheckCounter + Blockdata[currentpos.y - offset, currentpos.x];
//現在位置と下のオフセット位置の値を加算して、10なら終了
if (result == 10)
{
//消去データをセット
Erasedata[currentpos.y, currentpos.x] = 1;
IsDeleteBlock = true;
for (int r = 0; r < offset; r++)
{
Erasedata[currentpos.y - r - 1, currentpos.x] = 1;
}
break;
}
else if (result < 10)
{
//データを加算
CheckCounter = result;
//オフセットを加算
offset++;
}
}
//下が0の場合ループ終了
else
{
break;
}
}
else
{
//範囲外のためループ終了
break;
}
}
}
今回は、消すブロックの判定と、消去用のデータの書き込みまでについて記載した
次回以降では、実際にどのように消しているかと、消した後下のブロックが消えた場合の処理について触れたいと思う
以上