うにてぃブログ

主にUnityとC#に関する記事を書いていきます

【Unity】ジグソーパズルの自動生成 ~4~

ジグソーの複数分割

ピースの生成はできましたが、最終的には一枚絵からジグソーを作成するため
分割数を指定して、それに応じたピースを生成するようにしていきます

ジグソーの境界

隣り合うジグソーの境界は同じものを使う必要がありますが
すべてのピースを時計回りで境界を作成すると境界の向きが変わってしまい
上手に作成することができなくなります

時計回りで作成した場合、
1つ目を「(0, 0) -> (0, 1) -> (1, 1) -> (1, 0)」とすると
2つ目は「(1, 0) -> (1, 1) -> (2, 1) -> (2, 0)」となる
境界部分は、1つ目は(1, 1) -> (1, 0) なのに対し 2つ目は(1, 0) -> (1, 1) となり
向きが合わない

f:id:hacchi_man:20200112225716p:plain

そのためピースの位置によってピースの作成する向きを下図のように変更する必要がある

f:id:hacchi_man:20200112230508p:plain

コード

ピース毎の外周取得の処理は以下のようになる

   // 反時計回り
    private static readonly Vector2Int[] clockwisePosition = { Vector2Int.zero, Vector2Int.right, Vector2Int.one, Vector2Int.up };
    // 時計回り
    private static readonly Vector2Int[] counterclockwisePosition = { Vector2Int.zero, Vector2Int.up, Vector2Int.one, Vector2Int.right };

    private static List<BezierPathSegment> GetPieceSegment(JigsawParam param, int x, int y, ref List<Border> borders)
    {
        var ret = new List<BezierPathSegment>();
        var isClockwise = (x + y) % 2 == 0;
        foreach (var position in isClockwise ? clockwisePosition : counterclockwisePosition)
        {
            var begin = new Vector2Int(x + position.x, y + position.y);
            var end = isClockwise
                ? new Vector2Int(position.y == 0 ? x + 1 : x, y + position.x)
                : new Vector2Int(x + position.y, position.x == 0 ? y + 1 : y);
                    
            // 端のピース
            if (
                begin.x == 0 && end.x == 0 ||
                begin.y == 0 && end.y == 0 ||
                begin.x == param.Horizontal && end.x == param.Horizontal ||
                begin.y == param.Vertical && end.y == param.Vertical
            )
            {
                ret.Add(new BezierPathSegment
                {
                    P0 = new Vector2(begin.x, begin.y),
                    P1 = new Vector2(end.x, end.y),
                    P2 = new Vector2(begin.x, begin.y),
                });
                continue;
            }

            var border = borders.Find(b => b.Begin == begin && b.End == end);
            if (border == null)
            {
                border = new Border(begin, end, GetBorder(begin, end));
                borders.Add(border);
            }

            ret.AddRange(border.Segments);
        }

        return ret;
    }

ジグソー生成

これにより分割数を指定すると自動でジグソーが生成されるようになった

f:id:hacchi_man:20200112232850p:plain