Exemple #1
0
    /**********************************************************************************/
    // определяем правила соединения блоков перед генерацией карты
    //
    /**********************************************************************************/
    protected void BuildRoadRules(int xSize, int ySize, float chanseOfConnection = 0.1f)
    {
        // проверки параметров
        if (xSize <= 0 || ySize <= 0 || chanseOfConnection < 0)
        {
            Debug.LogError("BuildRoadRules: Wrong arguments! " + "xSize " + xSize + " ySize " + ySize + "chanseOfConnection " + chanseOfConnection);
            return;
        }

        // генерируем новые правила соединений
        for (int i = 0; i < xSize; i++)
        {
            for (int z = 0; z < ySize; z++)
            {
                for (int direction = (int)Base.DIREC.DOWN; direction <= (int)Base.DIREC.LEFT; direction++)
                {
                    float currectConnectionChance = Random.Range(0.0f, 1.0f);
                    if (currectConnectionChance <= chanseOfConnection)
                    {
                        BlockDescriptorImitation bd = m_blockRoadRulesDescriptor[i, z];
                        if (bd.RoadConnections[direction] != ROAD_CONNECTION_STATUS.BLOCKED)
                        {
                            bd.RoadConnections[direction] = ROAD_CONNECTION_STATUS.NEEDED;
                        }

                        UpdateRulesForBlock(i, z, bd.RoadConnections);
                    }
                }
            }
        }
    }
    /**********************************************************************************/
    // BlockDescriptorImitation копирующий конструктор
    //
    /**********************************************************************************/
    public BlockDescriptorImitation(BlockDescriptorImitation other)
    {
        RoadConnections = new ROAD_CONNECTION_STATUS[(int)Base.DIREC.NUM_OF_DIRECTIONS];

        for (int direction = (int)Base.DIREC.DOWN; direction < (int)Base.DIREC.NUM_OF_DIRECTIONS; direction++)
        {
            RoadConnections[direction] = other.RoadConnections[direction];
        }
    }
Exemple #3
0
 /**********************************************************************************/
 // функция передающая информацию о соединениях блоков друг с другом
 //
 /**********************************************************************************/
 public void ApplyBlockConnectionData(BlockDescriptorImitation[,] blockConnectionData)
 {
     for (int x = 0; x < m_xSizeOfMap; x++)
     {
         for (int y = 0; y < m_ySizeOfMap; y++)
         {
             m_blockConnectionData[x, y] = new BlockDescriptorImitation(blockConnectionData[x, y]);
         }
     }
 }
Exemple #4
0
    /**********************************************************************************/
    // записываем правила дорог в дескриптор блока
    // как правило это используется для генерируемых блоков
    //
    /**********************************************************************************/
    public void SetRoadRulesToBlock(BlockDescriptor descriptor, int x, int y)
    {
        // проверки параметров
        if (x < 0 || y < 0 || descriptor == null)
        {
            Debug.LogError("SetRoadRulesToBlock: Wrong arguments! " + "x " + x + " y " + y + "descriptor is null? " + (descriptor == null).ToString());
            return;
        }

        BlockDescriptorImitation bd = m_blockRoadRulesDescriptor[x, y];

        for (int direction = (int)Base.DIREC.DOWN; direction < (int)Base.DIREC.NUM_OF_DIRECTIONS; direction++)
        {
            descriptor.RoadConnections[direction] = bd.RoadConnections[direction];
        }
    }
Exemple #5
0
    /**********************************************************************************/
    // маркируем клетку по статусу проходимости
    //
    /**********************************************************************************/
    private void MarkCellWayStatus(int xPoint, int yPoint, bool cellIsFree)
    {
        // маркеруем соседние проходы в соответсвии со статусом текущей клетки
        ROAD_CONNECTION_STATUS status = ROAD_CONNECTION_STATUS.POSSIBLE;

        if (cellIsFree == false)
        {
            status = ROAD_CONNECTION_STATUS.BLOCKED;
        }

        // верхняя точка
        BlockDescriptorImitation bdi = GetGlobalConnectionCell(xPoint, yPoint + 1);

        if (bdi != null)
        {
            bdi.RoadConnections[(int)Base.DIREC.DOWN] = status;
        }

        // нижняя точка
        bdi = GetGlobalConnectionCell(xPoint, yPoint - 1);
        if (bdi != null)
        {
            bdi.RoadConnections[(int)Base.DIREC.UP] = status;
        }

        // левая точка
        bdi = GetGlobalConnectionCell(xPoint - 1, yPoint);
        if (bdi != null)
        {
            bdi.RoadConnections[(int)Base.DIREC.RIGHT] = status;
        }

        // правая точка
        bdi = GetGlobalConnectionCell(xPoint + 1, yPoint);
        if (bdi != null)
        {
            bdi.RoadConnections[(int)Base.DIREC.LEFT] = status;
        }
    }
Exemple #6
0
    /**********************************************************************************/
    // возвращаем информацию о возможных переходах между кдетками
    //
    /**********************************************************************************/
    BlockDescriptorImitation GetGlobalConnectionCell(int x, int y)
    {
        // проверяем координаты
        if (x >= m_connectionGlobalMap.GetLength(0) || x < 0)
        {
            return(null);
        }

        if (y >= m_connectionGlobalMap.GetLength(1) || y < 0)
        {
            return(null);
        }

        // если BDI ещё не использовался(создавался) - создаём
        if (m_connectionGlobalMap[x, y] == null)
        {
            m_connectionGlobalMap[x, y] = new BlockDescriptorImitation();
        }

        BlockDescriptorImitation bdi = m_connectionGlobalMap[x, y];

        return(bdi);
    }
Exemple #7
0
    /**********************************************************************************/
    // проверяем, подойдёт ли блок в эту позицию
    //
    /**********************************************************************************/
    public bool IsBlockOk(GameObject block, int x, int y)
    {
        // проверка параметров
        if (block == null || x <= 0 || y <= 0)
        {
            Debug.LogError("IsBlockOk: wrong argument " + "block is null? " + (block == null).ToString() + " x " + x + " y " + y);
            return(false);
        }

        BlockDescriptor bd = block.GetComponent <BlockDescriptor>();

        if (bd == null)
        {
            Debug.LogError("bd descriptor is null!");
            return(false);
        }

        BlockDescriptorImitation bdToCompaire = m_blockRoadRulesDescriptor[x, y];

        if (bdToCompaire == null)
        {
            Debug.LogError("bdToCompaire descriptor is null!");
            return(false);
        }

        // проверяем все стороны на возможность подключения дорог
        for (int direction = (int)Base.DIREC.DOWN; direction < (int)Base.DIREC.NUM_OF_DIRECTIONS; direction++)
        {
            if ((bdToCompaire.RoadConnections[direction] == ROAD_CONNECTION_STATUS.BLOCKED || bd.RoadConnections[direction] == ROAD_CONNECTION_STATUS.BLOCKED) &&
                (bdToCompaire.RoadConnections[direction] == ROAD_CONNECTION_STATUS.NEEDED || bd.RoadConnections[direction] == ROAD_CONNECTION_STATUS.NEEDED))
            {
                return(false);
            }
        }

        return(true);
    }
    /**********************************************************************************/
    // Test3_3
    // тест для BuildRoadRules функции
    //
    /**********************************************************************************/
    string Test3_3(ref bool result)
    {
        string Name = "BuildRoadRules 3";

        // тест
        int xSize = 9;
        int ySize = 9;

        m_blockRoadRulesDescriptor = new BlockDescriptorImitation[xSize, ySize];

        // подготавливаем структуры для теста
        for (int x = 0; x < xSize; x++)
        {
            for (int y = 0; y < ySize; y++)
            {
                BlockDescriptorImitation bd = new BlockDescriptorImitation();

                // для начала устанавливаем, что все соединения возможны
                bd.RoadConnections[(int)Base.DIREC.DOWN]  = ROAD_CONNECTION_STATUS.POSSIBLE;
                bd.RoadConnections[(int)Base.DIREC.LEFT]  = ROAD_CONNECTION_STATUS.POSSIBLE;
                bd.RoadConnections[(int)Base.DIREC.UP]    = ROAD_CONNECTION_STATUS.POSSIBLE;
                bd.RoadConnections[(int)Base.DIREC.RIGHT] = ROAD_CONNECTION_STATUS.POSSIBLE;

                // выставляем ограничители от краёв карты
                // блоки у краёв карты не должны соединяться с лесом
                if (x == 0)
                {
                    bd.RoadConnections[(int)Base.DIREC.LEFT] = ROAD_CONNECTION_STATUS.BLOCKED;
                }
                if (y == 0)
                {
                    bd.RoadConnections[(int)Base.DIREC.DOWN] = ROAD_CONNECTION_STATUS.BLOCKED;
                }

                if (x == xSize - 1)
                {
                    bd.RoadConnections[(int)Base.DIREC.RIGHT] = ROAD_CONNECTION_STATUS.BLOCKED;
                }
                if (y == ySize - 1)
                {
                    bd.RoadConnections[(int)Base.DIREC.UP] = ROAD_CONNECTION_STATUS.BLOCKED;
                }

                this.m_blockRoadRulesDescriptor[x, y] = bd;
            }
        }

        this.BuildRoadRules(xSize, ySize);

        // проверяем, что при стандартных настройках мы вносим какое-то кол-во рандома в карту
        // для успешного прохождения теста достаточно всего одного коннекшена
        bool isFine = false;

        for (int x = 1; x < xSize - 1; x++)
        {
            for (int y = 1; y < ySize - 1; y++)
            {
                if (this.m_blockRoadRulesDescriptor[x, y].RoadConnections[(int)Base.DIREC.DOWN] == ROAD_CONNECTION_STATUS.NEEDED ||
                    this.m_blockRoadRulesDescriptor[x, y].RoadConnections[(int)Base.DIREC.LEFT] == ROAD_CONNECTION_STATUS.NEEDED ||
                    this.m_blockRoadRulesDescriptor[x, y].RoadConnections[(int)Base.DIREC.RIGHT] == ROAD_CONNECTION_STATUS.NEEDED ||
                    this.m_blockRoadRulesDescriptor[x, y].RoadConnections[(int)Base.DIREC.UP] == ROAD_CONNECTION_STATUS.NEEDED
                    )
                {
                    isFine = true;
                }
            }
        }

        result = isFine;

        return(Name);
    }
    /**********************************************************************************/
    // Test3_2
    // тест для BuildRoadRules функции
    //
    /**********************************************************************************/
    string Test3_2(ref bool result)
    {
        string Name = "BuildRoadRules 2";

        // тест
        int xSize = 11;
        int ySize = 11;

        m_blockRoadRulesDescriptor = new BlockDescriptorImitation[xSize, ySize];

        // подготавливаем структуры для теста
        for (int x = 0; x < xSize; x++)
        {
            for (int y = 0; y < ySize; y++)
            {
                BlockDescriptorImitation bd = new BlockDescriptorImitation();

                // для начала устанавливаем, что все соединения возможны
                bd.RoadConnections[(int)Base.DIREC.DOWN]  = ROAD_CONNECTION_STATUS.POSSIBLE;
                bd.RoadConnections[(int)Base.DIREC.LEFT]  = ROAD_CONNECTION_STATUS.POSSIBLE;
                bd.RoadConnections[(int)Base.DIREC.UP]    = ROAD_CONNECTION_STATUS.POSSIBLE;
                bd.RoadConnections[(int)Base.DIREC.RIGHT] = ROAD_CONNECTION_STATUS.POSSIBLE;

                // выставляем ограничители от краёв карты
                // блоки у краёв карты не должны соединяться с лесом
                if (x == 0)
                {
                    bd.RoadConnections[(int)Base.DIREC.LEFT] = ROAD_CONNECTION_STATUS.BLOCKED;
                }
                if (y == 0)
                {
                    bd.RoadConnections[(int)Base.DIREC.DOWN] = ROAD_CONNECTION_STATUS.BLOCKED;
                }

                if (x == xSize - 1)
                {
                    bd.RoadConnections[(int)Base.DIREC.RIGHT] = ROAD_CONNECTION_STATUS.BLOCKED;
                }
                if (y == ySize - 1)
                {
                    bd.RoadConnections[(int)Base.DIREC.UP] = ROAD_CONNECTION_STATUS.BLOCKED;
                }

                this.m_blockRoadRulesDescriptor[x, y] = bd;
            }
        }

        this.BuildRoadRules(xSize, ySize, 1.0f);

        // проверяем, что все до одного правила в центральной части карты были установлены
        bool isFine = true;

        for (int x = 1; x < xSize - 1; x++)
        {
            for (int y = 1; y < ySize - 1; y++)
            {
                if (this.m_blockRoadRulesDescriptor[x, y].RoadConnections[(int)Base.DIREC.DOWN] != ROAD_CONNECTION_STATUS.NEEDED ||
                    this.m_blockRoadRulesDescriptor[x, y].RoadConnections[(int)Base.DIREC.LEFT] != ROAD_CONNECTION_STATUS.NEEDED ||
                    this.m_blockRoadRulesDescriptor[x, y].RoadConnections[(int)Base.DIREC.RIGHT] != ROAD_CONNECTION_STATUS.NEEDED ||
                    this.m_blockRoadRulesDescriptor[x, y].RoadConnections[(int)Base.DIREC.UP] != ROAD_CONNECTION_STATUS.NEEDED
                    )
                {
                    isFine = false;
                }
            }
        }

        result = isFine;

        return(Name);
    }
Exemple #10
0
    /**********************************************************************************/
    // обновляем правила дорог для блока
    // если этого не сделать, то возможны колизии в соседних блоках, особенно это касается предопределённых блоков
    //
    /**********************************************************************************/
    public void UpdateRulesForBlock(int x, int y, ROAD_CONNECTION_STATUS[] roadConnections)
    {
        // проверки параметров
        if (x < 0 || y < 0 || roadConnections == null || roadConnections.Length != (int)Base.DIREC.NUM_OF_DIRECTIONS)
        {
            Debug.LogError("UpdateRulesForBlock: Wrong arguments! " + "x " + x + " y " + y + "roadConnections is null? " + (roadConnections == null).ToString() + " roadConnections.Length " + roadConnections.Length);
            return;
        }

        // обновляем правила для текущего и соседних блоков
        for (int i = 0; i < (int)Base.DIREC.NUM_OF_DIRECTIONS; i++)
        {
            if (roadConnections[i] != ROAD_CONNECTION_STATUS.BLOCKED)
            {
                m_blockRoadRulesDescriptor[x, y].RoadConnections[i] = ROAD_CONNECTION_STATUS.NEEDED;
                roadConnections[i] = ROAD_CONNECTION_STATUS.NEEDED;
            }
            else
            {
                m_blockRoadRulesDescriptor[x, y].RoadConnections[i] = ROAD_CONNECTION_STATUS.BLOCKED;
            }
        }

        // проходим по окрестным блокам и обновляем условия
        // правила должны быть синхронизированы в соседних блоках
        for (int direction = (int)Base.DIREC.DOWN; direction < (int)Base.DIREC.NUM_OF_DIRECTIONS; direction++)
        {
            Point blockToUpdateCor = new Point(x, y);
            switch (direction)
            {
            case (int)Base.DIREC.DOWN:
                blockToUpdateCor.y--;
                break;

            case (int)Base.DIREC.UP:
                blockToUpdateCor.y++;
                break;

            case (int)Base.DIREC.LEFT:
                blockToUpdateCor.x--;
                break;

            case (int)Base.DIREC.RIGHT:
                blockToUpdateCor.x++;
                break;

            default:
                Debug.LogError("PrepareBluprintOfRoads: wrong direction!");
                break;
            }

            // проверяем координыты
            if (blockToUpdateCor.x < 0 || blockToUpdateCor.x >= m_blockRoadRulesDescriptor.GetLength(0) || blockToUpdateCor.y < 0 || blockToUpdateCor.y >= m_blockRoadRulesDescriptor.GetLength(1))
            {
                continue;
            }

            BlockDescriptorImitation blockToUpdates = m_blockRoadRulesDescriptor[blockToUpdateCor.x, blockToUpdateCor.y];
            Base.DIREC connectionToUpdate           = Base.InvertDirection(direction);

            // синхронизируем
            blockToUpdates.RoadConnections[(int)connectionToUpdate] = m_blockRoadRulesDescriptor[x, y].RoadConnections[(int)direction];
        }
    }
Exemple #11
0
    /**********************************************************************************/
    // проверка доступности блоков
    // если какие-то правила мешают доступности блоков - это необходимо исправить
    //
    /**********************************************************************************/
    protected bool CheckRoadRules(int xSize, int ySize)
    {
        // проверки параметров
        if (xSize <= 0 || ySize <= 0)
        {
            Debug.LogError("CheckRoadRules: Wrong size of map! " + xSize.ToString() + ":" + ySize.ToString());
            return(false);
        }


        // начинаем проверку соединений с левого нижнего угла
        // волновой алгорим
        Point startPoint = new Point(0, 0);
        LinkedList <Point> pointsToProcess = new LinkedList <Point>();

        pointsToProcess.AddFirst(startPoint);

        // вспомогательные структуры для подсчёта кол-ва соединений
        int linkedBlocksCounter = 0;

        bool[,] connectedBlocks = new bool[xSize, ySize];

        for (int i = 0; i < xSize; i++)
        {
            for (int y = 0; y < ySize; y++)
            {
                connectedBlocks[i, y] = false;
            }
        }
        connectedBlocks[0, 0] = true;
        linkedBlocksCounter++;

        while (pointsToProcess.Count > 0)
        {
            Point pointToCheck = pointsToProcess.First.Value;
            pointsToProcess.RemoveFirst();

            BlockDescriptorImitation bd = m_blockRoadRulesDescriptor[pointToCheck.x, pointToCheck.y];

            if (bd.RoadConnections[(int)Base.DIREC.DOWN] != ROAD_CONNECTION_STATUS.BLOCKED)
            {
                Point newPointToCheck = new Point(pointToCheck.x, pointToCheck.y - 1);
                // если точка ещё не была достижима - увеличиваем счётчик и маркируем её как достижимую
                if (!connectedBlocks[newPointToCheck.x, newPointToCheck.y])
                {
                    connectedBlocks[newPointToCheck.x, newPointToCheck.y] = true;
                    linkedBlocksCounter++;
                    pointsToProcess.AddLast(newPointToCheck);
                }
            }

            if (bd.RoadConnections[(int)Base.DIREC.UP] != ROAD_CONNECTION_STATUS.BLOCKED)
            {
                Point newPointToCheck = new Point(pointToCheck.x, pointToCheck.y + 1);
                // если точка ещё не была достижима - увеличиваем счётчик и маркируем её как достижимую
                if (!connectedBlocks[newPointToCheck.x, newPointToCheck.y])
                {
                    connectedBlocks[newPointToCheck.x, newPointToCheck.y] = true;
                    linkedBlocksCounter++;
                    pointsToProcess.AddLast(newPointToCheck);
                }
            }

            if (bd.RoadConnections[(int)Base.DIREC.LEFT] != ROAD_CONNECTION_STATUS.BLOCKED)
            {
                Point newPointToCheck = new Point(pointToCheck.x - 1, pointToCheck.y);
                // если точка ещё не была достижима - увеличиваем счётчик и маркируем её как достижимую
                if (!connectedBlocks[newPointToCheck.x, newPointToCheck.y])
                {
                    connectedBlocks[newPointToCheck.x, newPointToCheck.y] = true;
                    linkedBlocksCounter++;
                    pointsToProcess.AddLast(newPointToCheck);
                }
            }

            if (bd.RoadConnections[(int)Base.DIREC.RIGHT] != ROAD_CONNECTION_STATUS.BLOCKED)
            {
                Point newPointToCheck = new Point(pointToCheck.x + 1, pointToCheck.y);
                // если точка ещё не была достижима - увеличиваем счётчик и маркируем её как достижимую
                if (!connectedBlocks[newPointToCheck.x, newPointToCheck.y])
                {
                    connectedBlocks[newPointToCheck.x, newPointToCheck.y] = true;
                    linkedBlocksCounter++;
                    pointsToProcess.AddLast(newPointToCheck);
                }
            }
        }


        if (linkedBlocksCounter != xSize * ySize)
        {
            return(false);
        }
        else
        {
            return(true);
        }
    }
Exemple #12
0
    /**********************************************************************************/
    // ресетим карту дорог и карту зависимостей
    // устанавливаем новые рандомные зависимости между блоками
    //
    /**********************************************************************************/
    public void ResetRoadMap(int xSize, int ySize, int SizeOfBlock)
    {
        // проверки параметров
        if (xSize <= 0 || ySize <= 0)
        {
            Debug.LogError("ResetRoadMap: Wrong size of map! " + xSize.ToString() + ":" + ySize.ToString());
            return;
        }

        // сбрасываем старые правила соединений
        m_blockRoadRulesDescriptor = new BlockDescriptorImitation[xSize, ySize];
        bool mapIsFine = false;

        while (!mapIsFine)
        {
            for (int x = 0; x < xSize; x++)
            {
                for (int y = 0; y < ySize; y++)
                {
                    BlockDescriptorImitation bd = new BlockDescriptorImitation();

                    // для начала устанавливаем, что все соединения возможны
                    bd.RoadConnections[(int)Base.DIREC.DOWN]  = ROAD_CONNECTION_STATUS.POSSIBLE;
                    bd.RoadConnections[(int)Base.DIREC.LEFT]  = ROAD_CONNECTION_STATUS.POSSIBLE;
                    bd.RoadConnections[(int)Base.DIREC.UP]    = ROAD_CONNECTION_STATUS.POSSIBLE;
                    bd.RoadConnections[(int)Base.DIREC.RIGHT] = ROAD_CONNECTION_STATUS.POSSIBLE;

                    // выставляем ограничители от краёв карты
                    // блоки у краёв карты не должны соединяться с лесом
                    if (x == 0)
                    {
                        bd.RoadConnections[(int)Base.DIREC.LEFT] = ROAD_CONNECTION_STATUS.BLOCKED;
                    }
                    if (y == 0)
                    {
                        bd.RoadConnections[(int)Base.DIREC.DOWN] = ROAD_CONNECTION_STATUS.BLOCKED;
                    }

                    if (x == xSize - 1)
                    {
                        bd.RoadConnections[(int)Base.DIREC.RIGHT] = ROAD_CONNECTION_STATUS.BLOCKED;
                    }
                    if (y == ySize - 1)
                    {
                        bd.RoadConnections[(int)Base.DIREC.UP] = ROAD_CONNECTION_STATUS.BLOCKED;
                    }

                    m_blockRoadRulesDescriptor[x, y] = bd;
                }
            }

            // определяем правила соединения блоков перед генерацией карты
            BuildRoadRules(xSize, ySize);

            // проверка доступности блоков и правка правил
            mapIsFine = CheckRoadRules(xSize, ySize);
        }

        // обновляем массив "дорожных" пометок
        m_roadObjectMap = new bool[xSize * SizeOfBlock, ySize *SizeOfBlock];
    }