見出し画像

[Unity Blocks 8]ピースの形をプログラムに記憶させる

一旦スクリプトによって置きたい場所にピースを置くことができました。

後はルールに則ってピースを置けるようにします。

基本的にはピースの位置関係からどこに置けるかを判定するのではなく、どこにどのピースを置いたかをプログラムで記憶し、判定していきます。その方がバグも少ないと思っています。

ピースの形をプログラムに記憶させる

各ピースはスクリプトを持っている設計にします。また、そのスクリプトの中にピースの形を持って置き、回転や反転などの動きも入れたいと思います。

まずはピースの形をプログラムに記憶させます。

ピースが持つスクリプトは

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Piece : MonoBehaviour
{
   [SerializeField]
   public List<int[]> Design{get; set;}
   
   void Start()
   {
       Design = PieceDesign.ReturnDesign(this.gameObject);
   }

   void Update()
   {
   }
}

こんな感じです。

(のちのちの変更ですが、変数Designはオブジェクトの位置などとは全く関係のない、独立したものなので、変数Designを持つクラスPieceInfoを持つPieceクラスにしました)

PieceDesign.ReturnDesignはstaticな関数で、インスタンスの生成なしで実行できるようにしています。

PieceDesignクラスは

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public static class PieceDesign
{
   static Dictionary<string, int[,]> DesignDict;

   public static List<int[]> ReturnDesign(GameObject ParentObj)
   {
       Vector3 Pivot = Vector3.zero;
       List<int[]> res = new List<int[]>();
       res.Add(new int[]{0,0});
       foreach (Transform ChildObj in ParentObj.transform)
       {
           if (ChildObj.gameObject.name == "Piece")
               Pivot = ChildObj.transform.position;
               break;
       }
       foreach (Transform ChildObj in ParentObj.transform)
       {
           if (ChildObj.gameObject.name == "Piece")
               continue;
           Vector3 Pos = (ChildObj.transform.position - Pivot) * 100;
           int[] ChildPoint = new int[2];
           ChildPoint[0] = -(int)(Mathf.Round(Pos.z));
           ChildPoint[1] = (int)(Mathf.Round(Pos.x));
           res.Add(ChildPoint);
       }
       return res;
   }
}

最初のforeach文で基点となるピースを探します。そこからの他のピースまでの距離を0.01m(=1cm)単位で整数に四捨五入して管理します。

ChildPointが持っている配列は[y軸, x軸]の形で保存しています。x,yの値を表す配列の [*,*]の部分は[x,y]と置きたいですが、[y,x]と置いた方がバグが少なくて済む感じがします。

今回のように2次元配列扱っている途中で中身を全て表示する場合、

縦の列(行)のループ
{
    横の列(列)のループ
    {
        1文字づつ表示
    }
}

こんな感じの書き方になってしまうためです。
表示の仕方も工夫すればなんとでもなりますが、受け入れた方がバグが少ないと感じました。

ちなみにUnity上では画面から見てボードの上部がZ軸の正の方向になっていますが、ボードをxy平面とらえての左上を原点とした場合にボードの下部がy軸の正になっています。そのためChildPoint[0]は符号を反転しています。

この実装なら回転を行う場合は全てのポイントを座標変換で良くなりそうです。

スクリプトを作成したらテストも一緒にしましょうね・・・

次回

この記事が気に入ったらサポートをしてみませんか?