射出されたテトリスブロックをフィールドにはめる方法と計算処理の作り方

Unity VRゲームの作り方

前回までは、フィールドの設定は衝突判定のみだったので、それ以外の機能を作成していきます。

前回の記事↓

Oculus Questのコントローラーからテトリスブロックを射出する処理
今回は、コントローラからブロックを発射する処理と、フィールドにくっつける処理を作成していきます。 前回の記事↓ 【事前準備】左右のコントローラの識別方法 まずは事前準備として、左右のどちらのコントローラかを識別させるための...

【事前準備】フィールドの設定

Field.csを開いてください。

フィールド配列の定義

まずは、フィールド上に配置されたブロックを管理しやすくするため、10×20の要素数の配列を用意します。下のコードを記述してください。

blocksは10×20の要素を持つ二次元配列として定義しています。パズルゲームでは、二次元配列を使ってブロックの管理をすることが多いので、Unityでパズルゲームを開発する際には覚えておくと良いです。

関数の説明

そして、blocksを初期化する関数も下のコードのように作成しましょう。

この関数をStart関数内に定義すれば、初期化は完了です。

ブロックをきれいにフィールドにはめる処理

では本題に入ります。

衝突したブロックの位置の取得

まずは、フィールドに衝突したブロックの位置を確認できるようにしましょう。まずは、スコアを表示させる3D Textを作成しましょう。Fieldに3Dオブジェクト→3D Textで作成します。名前は「ScoreView」にしてください。

設定は以下のようにしてください。(Textは「Sample」でなくても問題ありません。)

このゲームオブジェクトに新しいスクリプトScoreView.csを作成してください。

コードは以下のように書いてください。60フレームだけTextを表示できるゲームオブジェクトを生成することができます。

そして、ScoreViewにScoreView.csをドラッグ&ドロップしてください。ScoreViewのtextMeshに自身のScoreViewをドラッグ&ドロップしてください。

ここまで作成したら、ScoreViewをプレハブに登録してください。これで文字を表示させるゲームオブジェクトの準備ができました。

さらに、ScoreViewを参照できるように、Field.csに以下を定義してください。

そして、以下のコードを書いてください。

コードを書き終えたらFieldのscoreViewObjにプレハブのScoreViewをドラッグ&ドロップしてください。

この状態で、実行してみましょう。すると、以下のようにぶつかった位置を確認することができるようになります。

綺麗にはめる処理を考えてみる

では、ブロックをきれいに並べるためにはどうすればいいか考えてみましょう。

まず、この処理を図に表すとこんな感じです。

今回は0.1×0.1のマスのグリッド上にブロックがきれいにはまるようにしたいので、ずれた分を自動的に直す処理を実装すればいいことが分かります。

もう少し拡大して、どのようにずれた分を直していくか考えてみましょう。

① 例えば、ブロックが(0.07, 0.06)の座標にあったとき、ブロックを(0.0, 0.0)と(0.1,0)の間のグリッドの位置に配置したいと考えます。この時、ブロックにはめるべき座標は(0.05,0.05)です。

② まず、基準となるグリッドに合わせることを考えます。この実装では、最も近い左下の座標を基準の座標と考えましょう。この例では、(0.07, 0.06)に最も近い左下の座標は(0, 0)なので、ブロックの座標を(0, 0)に設定していきます。

 

③ あとは、基準の座標から(0.05, 0.05)だけ座標をずらせばグリッド上にはめられます。

しかし、この手順の②にあたる左下の座標の取得方法をどのように実装するのでしょうか?

解決策として、プログラムのキャストをうまく利用して②を実装していくことを考えます。

まず、x,y座標を同時に考えると混乱するため、x座標のみグリッド上に合わせる計算方法を考えます。少し複雑なので、上の図を見ながら読んでください。

まず、bは現在のブロックのx座標(1.09)、gは基準の座標(1.0)、uはグリッドの長さ(0.1)とします。この時、まず、b/uにより、uの大きさ分だけbを大きくします。今回の例では、「1.09 / 0.1 = 10.9」となります。

ここに(int)(b/u)と書いてint型でキャストを行います。すると「(int)(10.9) = 10」となり、整数のみが取り出せるようになります。

次に、その全体を(float){(int)(b/u)}によりfloat型にキャストします。これは、次の計算の際に小数の値にするためです。つまり、「(float)(10) = 10.0」みたいな感じになります。

最後に、キャストした値をuで割ります。結果は「10.0 × 0.1 = 1.0」となります。この数値はgと等しくなっていることが分かります

綺麗にはめる処理の実装

では、実際にこの計算を追加していきましょう。

以下のコードを記述してください。

先ほどの計算を行い、その結果のgを衝突したブロックの座標に反映させています。

また、衝突する前にブロックが回転してしまうため、向きもリセットを行っています。

この状態で実行してみましょう。きれいにブロックがはまる様子が確認できたでしょうか?

 

配置されたブロックを把握する処理

では最後に、配置されたブロックがどの場所のブロックかを検知する方法について説明していきます。まず、今回のフィールドの位置とサイズを確認しておきましょう。Fieldを以下のように設定してください。

すると、4端の位置は以下のようになります。

今回は、左下の(-0.4,0.1)にブロックがあるときblock[0,0]をtrueにすることを考えます。つまり、(-0.3,0.1)にブロックがあるときはblock[1,0]がtrueになります。これを実装していきましょう。

座標値の求め方について説明しておきます。Fieldのx座標のScaleは0.1であるため、スケールをかける必要があります。

[FIeldのx座標] + ([Fieldのxローカルスケール] × [Leftのローカルx座標]) = Leftのワールドx座標
で計算できます。つまり、
0.05 + (0.1 × -5.5) = 0.05 – 0.55 = -0.45
となります。Rightなど他の位置に関しても同様の計算で求めることができます。

ここまでの内容を踏まえて、出来上がったのが以下のコードです(score表示の座標変数もpからbに変更しています)。

まず、pxとpyに左下の座標を設定します。そして、bx,byにはどの位置のブロックなのかを計算した結果を格納しています。最後に、blocks[bx,by]をtrueにすることでブロックを配置した個所をtrueにしています。

この状態で実行して確認してみましょう。以下のようにブロックがきれいにはまるようになったでしょうか?

次回予告

次回は、テトリスのゲームのルールの肝であるテトリスブロックの射出処理を作成していきます。

次回の記事↓

射出されたテトリスブロックをフィールドにはめる方法と計算処理の作り方
前回までは、フィールドの設定は衝突判定のみだったので、それ以外の機能を作成していきます。 前回の記事↓ 【事前準備】フィールドの設定 Field.csを開いてください。 フィールド配列の定義 まずは、フィールド上に配置...

 

【必見】無料資料請求でスクエアエニックスのゲーム開発の企画動画が見れる学校アリ
令和時代のゲームクリエイターになるための必須スキルがUnity。未経験からでもUnityを学んでオリジナルゲーム制作&ゲーム会社就職が可能なゲーム専門学校・プログラミングスクールの情報をオンライン&対面形式に分けてまとめました。 無料資料請求でスクエアエニックスのゲーム開発企画の動画もらえるので見てみるといいですよ。
Unity VRゲームの作り方
unity入門の森 ゲームの作り方

コメント

タイトルとURLをコピーしました