лабиринт с BSP генерацией в unity3d

Делаю курсовую для универа - 3d лабиринт на unity. Вот сам алгоритм генерации лабиринта

using UnityEngine;
using System.Collections;

public class Leaf 
{
    private int x; // размер карты по х
    private int y; // размер карты по у
    private int w;
    private int h;
    private bool connected;
    private int ID;

    private int RBH; // количество листов по высоте и ширине
    private int RBW;
    private int RH; // длины листов
    private int RW;
    private int MinX;
    private int MinY;
    private int NX; // номера листов
    private int NY;
    private int NumberOfRooms;
    private Vector3 Position;
    private Vector3 triggerPosition;

    private char freeSpace='$';
    private char border='#';
    private char coridor='@';

    public Leaf(){
        x = 0;
        y = 0;
        w = 0;
        h = 0;
        connected = false;
        ID = -1;
    }

    public char getChar(char ch){
        if (ch == 'f')
            return freeSpace;
        else if (ch == 'b')
            return border;
        else if (ch == 'c')
            return coridor;
        else
            return 'f';
    }

    public Vector3 getTriggerZone(){
        return triggerPosition;
    }

    public Vector3 getStartPosition(){
        return Position;
    }

    public int getX(){
        return x;
    }

    public int getY(){
        return y;
    }

    public int getW(){
        return w;
    }

    public int getH(){
        return h;
    }

    public int GetNumberOfRooms(){
        return NumberOfRooms;
    }

    public void GenerateMap(ref char [,] grid,int X,int Y){

        for (int i = 0; i < Y; i++) {
            for (int j = 0; j < X; j++) {
                grid [i,j] = freeSpace;
            }
        }

    }

    public int GetAmountOfRooms(int X,int Y,int N){

        int RealNumberOfRooms;
        NumberOfRooms = N;
        RBH=(int)Mathf.Sqrt(NumberOfRooms);
        RBW=(int)NumberOfRooms/RBH;

        int _difference=NumberOfRooms-RBH*RBW;

        if(_difference==0)
        {
            RealNumberOfRooms=NumberOfRooms;
        }
        else
        {
            if(RBH>RBW)
            {
                RBW++;
            }
            else if(RBW>RBH)
            {
                RBH++;
            }
            else
            {
                if(Random.Range(0.0f,1.0f)>0.5f)
                {
                    RBW++;
                }
                else RBH++;
            }

        }
        RealNumberOfRooms=RBH*RBW;

        int temp;

        if(X>Y)
        {
            if(RBW<RBH)
            {
                temp=RBH;
                RBH=RBW;
                RBW=temp;
                temp=0;
            }
        }
        else if( X < Y )
        {
            if(RBW > RBH)
            {
                temp=RBW;
                RBW=RBH;
                RBH=temp;
                temp=0;
            }
        }
        else
        {
            if(Random.Range(0.0f,1.0f)>0.5f)
            {
                temp=RBW;
                RBW=RBH;
                RBH=temp;
                temp=0;
            }
            else
            {
                temp=RBH;
                RBH=RBW;
                RBW=temp;
                temp=0;
            }
        }

        RH=Y/RBH;
        RW=X/RBW;

        return RealNumberOfRooms;
    }

    public void GenerateLeafs(ref char [,] grid,int X,int Y,int N){
        int amount=GetAmountOfRooms(X,Y,N);
        Leaf [] leafs = new Leaf[amount];

        for (int i = 0; i < amount; i++) {
            leafs[i] = new Leaf();
        }

        MinX=(int)RW/2;
        MinY=(int)RH/2;

        for(int i=0;i<amount;i++)
        {

            leafs[i].connected=false;
            leafs[i].ID=-1;
        }

        for(int A=0;A<amount;A++)
        {
            NX=(int)A%RBW;
            NY=(int)A/RBW;

            //Локальные координаты
            leafs[A].x=Random.Range(0,(RW-MinX-1));
            leafs[A].y=Random.Range(0,(RH-MinY-1));
            // Генерируем высоту и ширину в зависимости от локальных координат
            leafs[A].w=Random.Range(MinX,(RW-leafs[A].x-1));
            leafs[A].h=Random.Range(MinY,(RH-leafs[A].y-1));
            // Переводим локальные координаты в глобальные
            leafs[A].x += (NX*RW+1);
            leafs[A].y += (NY*RH+1);



            for (int i = leafs[A].y; i < leafs[A].y + leafs[A].h; i++)
            {
                for (int j = leafs[A].x; j < leafs[A].x + leafs[A].w; j++)
                {
                    //  Debug.Log ("i:" + i + " j:" + j + "Number of Room:" + A);
                    grid[i, j] = border;
                }
            }
        }

        /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
        Position = new Vector3(leafs[0].getX() + leafs[0].getW() / 2, 0.5f, leafs[0].getY() + leafs[0].getH() / 2);
        triggerPosition = new Vector3(leafs[amount - 1].getX() + leafs[amount - 1].getW() / 2, 0.5f, leafs[amount - 1].getY() + leafs[amount - 1].getH() / 2);

        int lastRoom = -1;


        // Коридоры
        for (int t = 0; t < amount; t++)
        {
            int cx1, cx2, cy1, cy2;
            int direction = Random.Range(1, 3);
            int counter = 0;
            do
            {
                if (!leafs[t].connected)
                {
                    switch (direction)
                    {
                        case 1:
                            {
                                if ((int)t / RBW < RBH - 1 && (leafs[t + RBW].ID == -1 || leafs[t + RBW].ID != leafs[t].ID) && !leafs[t + RBW].connected)
                                {
                                    cx1 = MinX + (int)t % RBW * RW;
                                    cx2 = cx1;

                                    if (leafs[t + RBW].x <= cx1 - 1 && leafs[t].x <= cx1 - 1)
                                    {
                                        cx1--;

                                    }

                                    if (((leafs[t + RBW].x + leafs[t + RBW].w) >= cx2 + 1) && ((leafs[t].x + leafs[t].w) >= cx2 + 1))
                                    {
                                        cx2++;

                                    }

                                    if (Random.value > 0.5f)
                                    {
                                        if (leafs[t + RBW].x <= cx1 - 1 && leafs[t].x <= cx1 - 1)
                                        {
                                            cx1--;

                                        }

                                        else if (((leafs[t + RBW].x + leafs[t + RBW].w) >= cx2 + 1) && ((leafs[t].x + leafs[t].w) >= cx2 + 1))
                                        {
                                            cx2++;

                                        }
                                    }

                                    cy1 = leafs[t].y + leafs[t].h;
                                    cy2 = leafs[t + RBW].y;
                                    for (int i = cy1; i < cy2; i++)
                                    {
                                        for (int j = cx1; j < cx2; j++)
                                        {

                                            grid[i, j] = coridor;
                                        }
                                    }
                                    leafs[t].connected = true;
                                }
                                break;
                            }
                        case 2:
                            {
                                if ((int)t % RBW < RBW - 1 && (leafs[t + 1].ID == -1 || leafs[t + 1].ID != leafs[t].ID) && !leafs[t + 1].connected)
                                {
                                    cy1 = MinY + (int)t / RBW * RH;
                                    cy2 = cy1;

                                    if (leafs[t + 1].y <= cy1 - 1 && leafs[t].y <= cy1 - 1)
                                    {
                                        cy1--;
                                    }

                                    if (leafs[t + 1].y + leafs[t + 1].h >= cy2 + 1 && leafs[t].y + leafs[t].h >= cy2 + 1)
                                    {
                                        cy2++;
                                    }

                                    if (Random.value > 0.5f)
                                    {
                                        if (leafs[t + 1].y <= cy1 - 1 && leafs[t].y <= cy1 - 1)
                                        {
                                            cy1--;
                                        }
                                        else if (leafs[t + 1].y + leafs[t + 1].h >= cy2 + 1 && leafs[t].y + leafs[t].h >= cy2 + 1)
                                        {
                                            cy2++;
                                        }
                                    }

                                    cx1 = leafs[t].x + leafs[t].w;
                                    cx2 = leafs[t + 1].x;
                                    for (int i = cy1; i < cy2; i++)
                                    {
                                        for (int j = cx1; j < cx2; j++)
                                        {

                                            grid[i, j] = coridor;
                                        }
                                    }
                                    leafs[t].connected = true;
                                }
                                break;
                            }
                    }
                }

                if (direction >= 3)
                    direction = 1;
                else direction++;

                if (counter == 2)
                    break;
                else counter++;

            } while (!leafs[t].connected);
        }
    }
}

В алгоритме я использую тайловую систему (то есть делю карту на равные зоны), но мне нужно использовать бинарное разделение пространства, тогда зоны не будут одинаковы, но карта всё равно будет заполняться равномерно. Можно ли как - нибудь аккуратно подправить код и не переделывать всё?


Ответы (0 шт):