Beispiel #1
0
    public virtual List <WayNode> GetSurround(Map map, WayNode center)
    {
        var result = new List <WayNode>();

        var centerPos = center.Current;
        var lPos      = centerPos + new int2(-1, 0);
        var rPos      = centerPos + new int2(1, 0);
        var uPos      = centerPos + new int2(0, 1);
        var dPos      = centerPos + new int2(0, -1);

        if (map.Avaliable(lPos))
        {
            result.Add(this[lPos]);
        }

        if (map.Avaliable(rPos))
        {
            result.Add(this[lPos]);
        }

        if (map.Avaliable(uPos))
        {
            result.Add(this[uPos]);
        }

        if (map.Avaliable(dPos))
        {
            result.Add(this[dPos]);
        }

        return(result);
    }
Beispiel #2
0
        public override bool StartFindWay(Map map, out WayNode path)
        {
            _openList.Clear();
            _closeList.Clear();

            _map = map;

            var startNode = map.FindWayData.Entrance;
            var endNode   = map.FindWayData.Destination;

            _startPos = startNode.Pos;
            _endPos   = endNode.Pos;
            //起点终点不可达
            if (!startNode.Walkable || !endNode.Walkable)
            {
                return(base.StartFindWay(map, out path));
            }

            var node = new AStarWayNode(_startPos, new int2(-1, -1));

            node.CalcF(map);
            _openList.Add(node);

            while (_openList.Count > 0)
            {
                //获得F最小的点
                var minFNode = GetMinF();
                //从列表中移除
                _openList.Remove(minFNode);
                //加入关闭列表
                _closeList.Add(minFNode);

                var surroundPoints = GetSurround(map, minFNode);

                foreach (var surroundPoint in surroundPoints)
                {
                    var surround = (AStarWayNode)surroundPoint;
                    //在关闭列表中 丢弃
                    if (!_closeList.Contains(surround) && !_openList.Contains(surround))
                    {
                        surround.CalcF(map);
                        surround.Parent = minFNode.Current;
                        if (surround.Current.Equals(map.FindWayData.Destination.Pos))
                        {
                            path = surround;
                            return(true);
                        }
                        else
                        {
                            _openList.Add(surround);
                        }
                    }
                }
            }

            return(base.StartFindWay(map, out path));
        }
Beispiel #3
0
    private void ShowPath(WayNode path)
    {
        var end = new int2(-1, -1);

        while (!path.Parent.Equals(Map.FindWayData.Entrance.Pos) && !path.Current.Equals(end))
        {
            path = FindWayOp[path.Parent];
            var floor = Map.FindWayData[path.Current];
            floor.SetFloor(FloorType.Way);
        }
    }
Beispiel #4
0
        public override List <WayNode> GetSurround(Map map, WayNode center)
        {
            var result = new List <WayNode>();

            var centerPos = center.Current;
            var lPos      = centerPos + new int2(-1, 0);
            var rPos      = centerPos + new int2(1, 0);
            var uPos      = centerPos + new int2(0, 1);
            var dPos      = centerPos + new int2(0, -1);

            if (map.Avaliable(lPos) && map.FindWayData[lPos].Walkable)
            {
                if (!WayNodes.ContainsKey(lPos))
                {
                    WayNodes[lPos] = new AStarWayNode(lPos, new int2(-1, -1));
                }

                result.Add(this[lPos]);
            }

            if (map.Avaliable(rPos) && map.FindWayData[rPos].Walkable)
            {
                if (!WayNodes.ContainsKey(rPos))
                {
                    WayNodes[rPos] = new AStarWayNode(rPos, new int2(-1, -1));
                }

                result.Add(this[rPos]);
            }

            if (map.Avaliable(uPos) && map.FindWayData[uPos].Walkable)
            {
                if (!WayNodes.ContainsKey(uPos))
                {
                    WayNodes[uPos] = new AStarWayNode(uPos, new int2(-1, -1));
                }

                result.Add(this[uPos]);
            }

            if (map.Avaliable(dPos) && map.FindWayData[dPos].Walkable)
            {
                if (!WayNodes.ContainsKey(dPos))
                {
                    WayNodes[dPos] = new AStarWayNode(dPos, new int2(-1, -1));
                }

                result.Add(this[dPos]);
            }

            return(result);
        }
Beispiel #5
0
        private (WayNode, bool) CheckPosNode(Floor parentFloor, Floor checkedFloor)
        {
            if (_map.Avaliable(checkedFloor.Pos))
            {
                if (checkedFloor.Walkable)
                {
                    var wayNode = new WayNode(checkedFloor.Pos, parentFloor.Pos);
                    var isReach = checkedFloor.Pos.Equals(_endPos);
                    return(wayNode, isReach);
                }
            }

            return(null, false);
        }
Beispiel #6
0
    /// <summary>
    /// Loads pathData & create path under editor mode.
    /// </summary>
    /// <param name="data">Data.</param>
    public void LoadPathInEditor(PathData data)
    {
        connection      = new Connection(data.connection.x, data.connection.y);
        gameObject.name = string.Format("Path {0}", data.connection.ToString());

        rt.anchoredPosition = Average(data.points);
        color = data.c;

        for (int i = 0; i < data.points.Length; i++)
        {
            GameObject go = Instantiate(prefab) as GameObject;
            go.name = gameObject.name + " Point." + i;
            go.transform.SetParent(transform.parent, false);

            WayNode node = go.AddComponent <WayNode>();
            node.c = (color != null)?color:Color.yellow;
            node.p = data.points[i];
            node.Match();
            nodes.Add(node);
        }
    }
Beispiel #7
0
    /**********************************************************************************/
    // строим путь из from в to
    // !!!!!!! используется ТОЛЬКО при построении системы указателей !!!!!!!
    //
    /**********************************************************************************/
    private void BuildPath(Point from, Point to)
    {
        if (from.IsSamePoint(to))
        {
            Debug.LogError("We cann't build path from 1 same point");
            return;
        }

        WayNode[,] bluprintOfRoad = new WayNode[m_xSizeOfMap, m_ySizeOfMap];
        for (int x = 0; x < m_xSizeOfMap; x++)
        {
            for (int y = 0; y < m_ySizeOfMap; y++)
            {
                bluprintOfRoad[x, y] = new WayNode();
            }
        }

        PrepareBluprintOfPath(bluprintOfRoad, from, to, m_blockConnectionData, m_sizeOfBlock * 4);

        // проходим по результирующему пути задом наперёд и запоминаем направление движения
        // для системы указателей важно только направление первого шага в пути
        Base.DIREC nextDirection = Base.DIREC.NO_DIRECTION;
        Point      toProcess     = new Point(to);

        do
        {
            WayNode nodeToProcess = bluprintOfRoad[toProcess.x, toProcess.y];
            toProcess.ShiftPoint(nodeToProcess.previusRoadDirection);
            nextDirection = Base.InvertDirection(nodeToProcess.previusRoadDirection);
        } while (!toProcess.IsSamePoint(from));

        // по окончанию обработки nextDirection содержит направление первого шага по достижению точки "to" из "from"
        // его и сохраняем в таблице

        int keyToMark    = GetSingKey(from.x, from.y);  // ключик блока "from"
        int keyToConnect = GetSingKey(to.x, to.y);      // ключик блока "to"

        m_singMap[keyToMark, keyToConnect] = nextDirection;
    }
Beispiel #8
0
    /**********************************************************************************/
    // просчитываем конкретную точку построения пути
    // проверяем её стоимость и на оснеовании проверки вносим коррективы в карту маршрутов
    //
    /**********************************************************************************/
    void CalculatePoint(WayNode[,] bluprintOfRoadMap, Point currentPoint, Point to, Base.DIREC prevPointDir, int currentWayCost, ref int nodeClosestDist,
                        LinkedList <Point> currentPontsToProcess, LinkedList <Point> nextIterationPontsToProcess)
    {
        int newX = currentPoint.x;
        int newY = currentPoint.y;

        // выбираем координаты новой точки в зависимости от положения предыдущей
        switch (prevPointDir)
        {
        case Base.DIREC.DOWN:
            newY++;
            break;

        case Base.DIREC.UP:
            newY--;
            break;

        case Base.DIREC.LEFT:
            newX++;
            break;

        case Base.DIREC.RIGHT:
            newX--;
            break;
        }

        // если координата удовлетворяет ...
        if (newX < 0 || newX >= bluprintOfRoadMap.GetLength(0) || newY < 0 || newY >= bluprintOfRoadMap.GetLength(1))
        {
            return;
        }

        WayNode wayNodeToCheck = bluprintOfRoadMap[newX, newY];

        // формирование цены прохода происходит из стоимости предыдущих клеток + стоимость прохода по клетке + загруженность пути
        int   possibleWayCost = currentWayCost + wayNodeToCheck.cellCost + m_trafficData[newX, newY];
        Point pointToCheck    = null;

        if (wayNodeToCheck.wayCost > possibleWayCost)
        {
            wayNodeToCheck.wayCost = possibleWayCost;
            wayNodeToCheck.previusRoadDirection = prevPointDir;
            pointToCheck = new Point(newX, newY);
        }
        else if (wayNodeToCheck.wayCost == possibleWayCost)
        {
            // в случае, если стоимости равны - в половине случаев переключаемся на новый путь для разнообразия
            if (Random.Range(0, 100) >= 50)
            {
                wayNodeToCheck.wayCost = possibleWayCost;
                wayNodeToCheck.previusRoadDirection = prevPointDir;
            }
        }

        // если мы нашли точку для просчёта - определяемся когда будем её просчитывать
        // если "квадратное" растояние меньше или равно самого близкого к целевой точке, то будем просчитывать её в первую очередь
        if (pointToCheck != null)
        {
            int dist = Mathf.Abs(pointToCheck.x - to.x) + Mathf.Abs(pointToCheck.y - to.y);

            if (dist == 0)
            {
                nodeClosestDist = 0;
                return;
            }
            else if (dist <= nodeClosestDist)
            {
                currentPontsToProcess.AddLast(pointToCheck);
                nodeClosestDist = dist;
            }
            else
            {
                nextIterationPontsToProcess.AddLast(pointToCheck);
            }
        }
    }
Beispiel #9
0
    /**********************************************************************************/
    // строим путь из точки from в точку to
    // результат записываем в bluprintOfPath
    //
    // @ bluprintOfPath - чертёж дороги (пустой, если не хотим накладывать какие-то ограничения и модификации поведения при поиске пути)
    // @ from - точка откуда строят путь
    // @ to - точка куда строят путь
    // @ map - карта с ограничением движений
    // @ maxCost - максимальная кол-во итераций при расчёте пути
    //
    /**********************************************************************************/
    void PrepareBluprintOfPath(WayNode[,] bluprintOfPath, Point from, Point to, BlockDescriptorImitation[,] map, int maxCost)
    {
        LinkedList <Point> currentPontsToProcess       = new LinkedList <Point>();
        LinkedList <Point> nextIterationPontsToProcess = new LinkedList <Point>();

        // устанавливаем стартовые параметры алгоритма - начальную точку и её стоимость пути
        bluprintOfPath[from.x, from.y].wayCost = 0;
        currentPontsToProcess.AddFirst(from);
        int possibleClosestDist = (Mathf.Abs(from.x - to.x) + Mathf.Abs(from.y - to.y)) * WayNode.GROUND_COST;



        int  nodeClosestDist  = possibleClosestDist;
        bool buildingComplite = false;
        int  maxSteps         = maxCost;

        while (!buildingComplite && maxSteps > 0)
        {
            maxSteps--;
            while (currentPontsToProcess.Count > 0)
            {
                // забираем точку для просчёта и работаем с ней
                Point currentPoint = currentPontsToProcess.First.Value;
                currentPontsToProcess.RemoveFirst();


                int currentWayCost = bluprintOfPath[currentPoint.x, currentPoint.y].wayCost;

                // просчитываем верхную точку, если соединение возможно
                if (map[currentPoint.x, currentPoint.y].RoadConnections[(int)Base.DIREC.UP] != ROAD_CONNECTION_STATUS.BLOCKED)
                {
                    CalculatePoint(bluprintOfPath, currentPoint, to, Base.DIREC.DOWN, currentWayCost, ref nodeClosestDist, currentPontsToProcess, nextIterationPontsToProcess);
                }

                // просчитываем нижнюю точку, если соединение возможно
                if (map[currentPoint.x, currentPoint.y].RoadConnections[(int)Base.DIREC.DOWN] != ROAD_CONNECTION_STATUS.BLOCKED)
                {
                    CalculatePoint(bluprintOfPath, currentPoint, to, Base.DIREC.UP, currentWayCost, ref nodeClosestDist, currentPontsToProcess, nextIterationPontsToProcess);
                }

                // просчитываем левую точку, если соединение возможно
                if (map[currentPoint.x, currentPoint.y].RoadConnections[(int)Base.DIREC.LEFT] != ROAD_CONNECTION_STATUS.BLOCKED)
                {
                    CalculatePoint(bluprintOfPath, currentPoint, to, Base.DIREC.RIGHT, currentWayCost, ref nodeClosestDist, currentPontsToProcess, nextIterationPontsToProcess);
                }

                // просчитываем правую точку, если соединение возможно
                if (map[currentPoint.x, currentPoint.y].RoadConnections[(int)Base.DIREC.RIGHT] != ROAD_CONNECTION_STATUS.BLOCKED)
                {
                    CalculatePoint(bluprintOfPath, currentPoint, to, Base.DIREC.LEFT, currentWayCost, ref nodeClosestDist, currentPontsToProcess, nextIterationPontsToProcess);
                }
            }


            // принимаем решение о дальнейших итерациях

            if (to.x < 0 || to.x > bluprintOfPath.GetLength(0) ||
                to.y < 0 || to.y > bluprintOfPath.GetLength(1))
            {
                Debug.LogError("Wrong position");
            }

            WayNode WayNodeFinal = bluprintOfPath[to.x, to.y];
            if (WayNodeFinal.wayCost == possibleClosestDist)
            {
                buildingComplite = true;
            }
            else
            {
                // если мы нашли путь (любой оптимальности) и при этом исчерпали возможности для построения маршрута - завершаем проектирование маршрута
                // так же завершаем поиск пути в случае исчерпания ходов построения пути (только при условии, что у нас есть хоть какой-то путь)
                if (WayNodeFinal.wayCost != WayNode.UNREACHABLE)
                {
                    if (maxSteps == 0 || nextIterationPontsToProcess.Count == 0)
                    {
                        buildingComplite = true;
                    }
                }
                // в противном случае продолжаем
                else
                {
                    // меняем местами коллекции
                    LinkedList <Point> supportPointer = currentPontsToProcess;
                    currentPontsToProcess       = nextIterationPontsToProcess;
                    nextIterationPontsToProcess = supportPointer;
                }
            }
        }


        if (!buildingComplite)
        {
            Debug.LogError("We cann't buld the path!!! From: " + from + ". To: " + to);
            Logger.CreatePathFinderErrorReport(bluprintOfPath, from, to, m_freeSpaceGlobalMap);
        }
    }
Beispiel #10
0
    /**********************************************************************************/
    // функция строящая путь между точками и возвращающая коллекцию точек для прохождения
    //
    /**********************************************************************************/
    LinkedList <Point> BuildSpecificWay(Point from, Point to)
    {
        LinkedList <Point> wayPoints = new LinkedList <Point>();

        // если точка старта совпадает с точкой конца пути - возвращаем пустую коллекцию
        if (from.IsSamePoint(to))
        {
            return(wayPoints);
        }

        // подготавливаем блюпринт пути
        // TODO: здоровый, подумать, можно ли оптимизировать расход памяти и времени
        WayNode[,] bluprintOfRoad = new WayNode[m_xSizeOfMap * m_sizeOfBlock, m_ySizeOfMap *m_sizeOfBlock];
        for (int x = 0; x < m_xSizeOfMap * m_sizeOfBlock; x++)
        {
            for (int y = 0; y < m_ySizeOfMap * m_sizeOfBlock; y++)
            {
                bluprintOfRoad[x, y] = new WayNode();
            }
        }

        PrepareBluprintOfPath(bluprintOfRoad, from, to, m_connectionGlobalMap, m_sizeOfBlock * 3);

        // проходим по результирующему пути задом наперёд и формируем список точек пути
        Point toProcess = new Point(to);
        int   maxSteps  = (from - to).GetSimpleLength() * 3; // устанавливаем ограничитель, но не меньше 20 шаговы

        if (maxSteps < 20)
        {
            maxSteps = 20;
        }

        do
        {
            WayNode nodeToProcess = bluprintOfRoad[toProcess.x, toProcess.y];
            wayPoints.AddLast(new Point(toProcess));
            // так же увеличиваем загруженность трафика на данном пути
            m_trafficData[toProcess.x, toProcess.y] += m_trafficIncrCost;
            toProcess.ShiftPoint(nodeToProcess.previusRoadDirection);
            maxSteps--;
        } while (!toProcess.IsSamePoint(from) && maxSteps > 0);

        if (maxSteps == 0)
        {
            if (!toProcess.IsSamePoint(from))
            {
                Logger.CreatePathFinderErrorReport(bluprintOfRoad, from, to, m_freeSpaceGlobalMap);
                Debug.LogError("ERROR!!! Path constraction was failed!!! from: " + from.ToString() + " to: " + to.ToString());
            }
        }

        // TODO: дополнительное выравнивание по точке начала пути способствует значительному возростанию точности и аккуратности прохождения маршрута
        // юнит, не цепляется за посторонние статичные объекты
        // с другой стороны, это иногда вызывает странное поведение, когда юнит делает короткое движение "туда-обратно" в точку начала маршрута (выравнивается)
        // а потом разворачивается на 180 градусов и продолжает движение к следующей точке маршрута (возможно решается по средствам регулировки точности при выполнении манёвров)

        // удаляем последнюю точку, так как она совподает с координатой from
        // wayPoints.RemoveLast();

        return(wayPoints);
    }
Beispiel #11
0
 public virtual bool StartFindWay(Map map, out WayNode path)
 {
     path = null;
     return(false);
 }
Beispiel #12
0
    public static void CreatePathFinderErrorReport(WayNode[,] bluprintOfPath, Point from, Point to, bool[,] freeSpaceMap)
    {
        string fileName = "PathFinderReport_";
        string logPath  = @"E:\Game Projects\Logs";
        string filePath = logPath + @"\" + fileName + s_errorReportIndex.ToString() + DateTime.Now.ToString("MM_dd_yyyy_HH-mm") + ".txt";

        if (!File.Exists(filePath))
        {
            // Create a file to write to.
            using (StreamWriter sw = File.CreateText(filePath))
            {
                sw.WriteLine("Path Finder Error Report");
                sw.WriteLine("We tryed to build path from: " + from.ToString() + " to: " + to.ToString());
                sw.WriteLine("************************");
            }
        }


        string headLine = "\t*";

        for (int x = 0; x < bluprintOfPath.GetLength(0); x++)
        {
            headLine += "\t" + x.ToString() + "#";
        }



        using (StreamWriter sw = File.AppendText(filePath))
        {
            sw.WriteLine(headLine);
        }

        for (int y = bluprintOfPath.GetLength(1) - 1; y >= 0; y--)
        {
            using (StreamWriter sw = File.AppendText(filePath))
            {
                sw.Write("\t" + y.ToString() + "#");
            }

            string str = "";
            for (int x = 0; x < bluprintOfPath.GetLength(0); x++)
            {
                if (freeSpaceMap[x, y])
                {
                    str += "\t" + "_";
                }
                else
                {
                    str += "\t" + "X";
                }
            }

            using (StreamWriter sw = File.AppendText(filePath))
            {
                sw.WriteLine(str);
            }
        }

        using (StreamWriter sw = File.AppendText(filePath))
        {
            sw.WriteLine(headLine);
        }


        using (StreamWriter sw = File.AppendText(filePath))
        {
            sw.WriteLine("************************");
        }



        using (StreamWriter sw = File.AppendText(filePath))
        {
            sw.WriteLine(headLine);
        }

        for (int y = bluprintOfPath.GetLength(1) - 1; y >= 0; y--)
        {
            using (StreamWriter sw = File.AppendText(filePath))
            {
                sw.Write("\t" + y.ToString() + "#");
            }

            string str = "";
            for (int x = 0; x < bluprintOfPath.GetLength(0); x++)
            {
                WayNode currentNode = bluprintOfPath[x, y];

                switch (currentNode.previusRoadDirection)
                {
                case Base.DIREC.DOWN:
                    str += "\t↓";
                    break;

                case Base.DIREC.UP:
                    str += "\t↑";
                    break;

                case Base.DIREC.LEFT:
                    str += "\t←";
                    break;

                case Base.DIREC.RIGHT:
                    str += "\t→";
                    break;

                case Base.DIREC.NO_DIRECTION:
                    str += "\t•";
                    break;
                }
            }

            using (StreamWriter sw = File.AppendText(filePath))
            {
                sw.WriteLine(str);
            }
        }


        using (StreamWriter sw = File.AppendText(filePath))
        {
            sw.WriteLine(headLine);
        }

        using (StreamWriter sw = File.AppendText(filePath))
        {
            sw.WriteLine("************************");
        }


        using (StreamWriter sw = File.AppendText(filePath))
        {
            sw.WriteLine(headLine);
        }
        for (int y = bluprintOfPath.GetLength(1) - 1; y >= 0; y--)
        {
            using (StreamWriter sw = File.AppendText(filePath))
            {
                sw.Write("\t" + y.ToString() + "#");
            }

            string str = "";
            for (int x = 0; x < bluprintOfPath.GetLength(0); x++)
            {
                WayNode currentNode = bluprintOfPath[x, y];

                if (currentNode.wayCost == WayNode.UNREACHABLE)
                {
                    str += "\t*";
                }
                else
                {
                    str += "\t" + currentNode.wayCost / WayNode.GROUND_COST;
                }
            }

            using (StreamWriter sw = File.AppendText(filePath))
            {
                sw.WriteLine(str);
            }
        }

        using (StreamWriter sw = File.AppendText(filePath))
        {
            sw.WriteLine(headLine);
        }

        using (StreamWriter sw = File.AppendText(filePath))
        {
            sw.WriteLine("************************");
        }

        using (StreamWriter sw = File.AppendText(filePath))
        {
            sw.WriteLine(headLine);
        }
        for (int y = bluprintOfPath.GetLength(1) - 1; y >= 0; y--)
        {
            using (StreamWriter sw = File.AppendText(filePath))
            {
                sw.Write("\t" + y.ToString() + "#");
            }

            string str = "";
            for (int x = 0; x < bluprintOfPath.GetLength(0); x++)
            {
                Point pointToPrint = new Point(x, y);

                if (pointToPrint.IsSamePoint(from))
                {
                    str += "\tS";
                }
                else if (pointToPrint.IsSamePoint(to))
                {
                    str += "\tE";
                }
                else
                {
                    str += "\t•";
                }
            }

            using (StreamWriter sw = File.AppendText(filePath))
            {
                sw.WriteLine(str);
            }
        }

        using (StreamWriter sw = File.AppendText(filePath))
        {
            sw.WriteLine(headLine);
        }

        using (StreamWriter sw = File.AppendText(filePath))
        {
            sw.WriteLine("************************");
            sw.WriteLine("Target point cost: " + bluprintOfPath[to.x, to.y].wayCost.ToString());
        }

        s_errorReportIndex++;
    }
Beispiel #13
0
        public override bool StartFindWay(Map map, out WayNode path)
        {
            _map = map;
            var startNode = map.FindWayData.Entrance;
            var endNode   = map.FindWayData.Destination;

            _endPos = endNode.Pos;
            //起点终点不可达
            if (!startNode.Walkable || !endNode.Walkable)
            {
                return(base.StartFindWay(map, out path));
            }

            //检查队列
            var queue = new Queue <Floor>();
            //已经检查过的点
            var checkedDic = new Dictionary <Floor, bool>();

            queue.Enqueue(startNode);

            while (queue.Count > 0)
            {
                var tmp    = queue.Dequeue();
                var tmpPos = tmp.Pos;
                var lPos   = tmpPos + new int2(-1, 0);
                var rPos   = tmpPos + new int2(1, 0);
                var uPos   = tmpPos + new int2(0, 1);
                var dPos   = tmpPos + new int2(0, -1);
                var lFloor = _map.FindWayData[lPos];
                var rFloor = _map.FindWayData[rPos];
                var uFloor = _map.FindWayData[uPos];
                var dFloor = _map.FindWayData[dPos];
                if (lFloor && !checkedDic.ContainsKey(lFloor))
                {
                    var w = CheckPosNode(tmp, lFloor);
                    if (w.Item1 != null)
                    {
                        WayNodes[lPos] = w.Item1;
                        queue.Enqueue(lFloor);
                        if (w.Item2)
                        {
                            path = w.Item1;
                            return(true);
                        }
                    }

                    checkedDic.Add(lFloor, true);
                }

                if (rFloor && !checkedDic.ContainsKey(rFloor))
                {
                    var w = CheckPosNode(tmp, rFloor);
                    if (w.Item1 != null)
                    {
                        WayNodes[rPos] = w.Item1;
                        queue.Enqueue(rFloor);
                        if (w.Item2)
                        {
                            path = w.Item1;
                            return(true);
                        }
                    }

                    checkedDic.Add(rFloor, true);
                }

                if (uFloor && !checkedDic.ContainsKey(uFloor))
                {
                    var w = CheckPosNode(tmp, uFloor);
                    if (w.Item1 != null)
                    {
                        WayNodes[uPos] = w.Item1;
                        queue.Enqueue(uFloor);
                        if (w.Item2)
                        {
                            path = w.Item1;
                            return(true);
                        }
                    }

                    checkedDic.Add(uFloor, true);
                }

                if (dFloor && !checkedDic.ContainsKey(dFloor))
                {
                    var w = CheckPosNode(tmp, dFloor);
                    if (w.Item1 != null)
                    {
                        WayNodes[dPos] = w.Item1;
                        queue.Enqueue(dFloor);
                        if (w.Item2)
                        {
                            path = w.Item1;
                            return(true);
                        }
                    }

                    checkedDic.Add(dFloor, true);
                }
            }

            return(base.StartFindWay(map, out path));
        }
Beispiel #14
0
    /**********************************************************************************/
    // просчитываем конкретную точку построения пути
    // проверяем её стоимость и на оснеовании проверки вносим коррективы в карту маршрутов
    //
    /**********************************************************************************/
    void CalculatePoint(BlockDescriptor descriptor, WayNode[,] bluprintOfRoadMap, Point currentPoint, Point to, Base.DIREC prevPointDir, int sizeOfBlock, int currentWayCost, ref int nodeClosestDist,
                        LinkedList <Point> currentPontsToProcess, LinkedList <Point> nextIterationPontsToProcess)
    {
        // проверки параметров
        if (currentPoint == null || to == null || descriptor == null || bluprintOfRoadMap == null || bluprintOfRoadMap.Length == 0)
        {
            Debug.LogError("CalculatePoint: Wrong arguments! " + "descriptor is null? " + (descriptor == null).ToString()
                           + " currentPoint is null? " + (currentPoint == null).ToString()
                           + " prevPointDir " + prevPointDir.ToString()
                           + " to is null? " + (to == null).ToString()
                           + " bluprintOfRoadMap is null? " + (bluprintOfRoadMap == null).ToString()
                           + " bluprintOfRoadMap.Length " + bluprintOfRoadMap.Length);
            return;
        }


        int newX = currentPoint.x;
        int newY = currentPoint.y;

        // выбираем координаты новой точки в зависимости от положения предыдущей
        switch (prevPointDir)
        {
        case Base.DIREC.DOWN:
            newY++;
            break;

        case Base.DIREC.UP:
            newY--;
            break;

        case Base.DIREC.LEFT:
            newX++;
            break;

        case Base.DIREC.RIGHT:
            newX--;
            break;
        }

        // если координата удовлетворяет ...
        if (newX < 0 || newX >= sizeOfBlock || newY < 0 || newY >= sizeOfBlock)
        {
            return;
        }

        // ... и место свободно для дорог - процессим
        if (descriptor.FreeWaysMap[newX, newY] == false)
        {
            return;
        }


        WayNode wayNodeToCheck  = bluprintOfRoadMap[newX, newY];
        int     possibleWayCost = currentWayCost + wayNodeToCheck.cellCost;
        Point   pointToCheck    = null;

        if (wayNodeToCheck.wayCost > possibleWayCost)
        {
            wayNodeToCheck.wayCost = possibleWayCost;
            wayNodeToCheck.previusRoadDirection = prevPointDir;
            pointToCheck = new Point(newX, newY);
        }
        else if (wayNodeToCheck.wayCost == possibleWayCost)
        {
            // в случае, если стоимости равны - в половине случаев переключаемся на новый путь для разнообразия
            if (Random.Range(0, 100) >= 50)
            {
                wayNodeToCheck.wayCost = possibleWayCost;
                wayNodeToCheck.previusRoadDirection = prevPointDir;
            }
        }

        // если мы нашли точку для просчёта - определяемся когда будем её просчитывать
        // если "квадратное" растояние меньше или равно самого близкого к целевой точке, то будем просчитывать её в первую очередь
        if (pointToCheck != null)
        {
            int dist = Mathf.Abs(pointToCheck.x - to.x) + Mathf.Abs(pointToCheck.y - to.y);

            if (dist == 0)
            {
                nodeClosestDist = 0;
                return;
            }
            else if (dist <= nodeClosestDist)
            {
                currentPontsToProcess.AddLast(pointToCheck);
                nodeClosestDist = dist;
            }
            else
            {
                nextIterationPontsToProcess.AddLast(pointToCheck);
            }
        }
    }
Beispiel #15
0
    /**********************************************************************************/
    // строим дорогу из точки from в точку to
    // результат записываем в bluprintOfRoadMap
    //
    /**********************************************************************************/
    void PrepareBluprintOfRoads(BlockDescriptor descriptor, WayNode[,] bluprintOfRoadMap, Point from, Point to, int sizeOfBlock)
    {
        // проверки параметров
        if (from == null || to == null || descriptor == null || bluprintOfRoadMap == null || bluprintOfRoadMap.Length == 0)
        {
            Debug.LogError("PrepareBluprintOfRoads: Wrong arguments! " + "descriptor is null? " + (descriptor == null).ToString()
                           + " from is null? " + (from == null).ToString()
                           + " to is null? " + (to == null).ToString()
                           + " bluprintOfRoadMap is null? " + (bluprintOfRoadMap == null).ToString()
                           + " bluprintOfRoadMap.Length " + bluprintOfRoadMap.Length);
            return;
        }

        LinkedList <Point> currentPontsToProcess       = new LinkedList <Point>();
        LinkedList <Point> nextIterationPontsToProcess = new LinkedList <Point>();

        // устанавливаем стартовые параметры алгоритма - начальную точку и её стоимость пути
        bluprintOfRoadMap[from.x, from.y].wayCost = 0;
        currentPontsToProcess.AddFirst(from);
        int possibleClosestDist = Mathf.Abs(from.x - to.x) + Mathf.Abs(from.y - to.y);



        int  nodeClosestDist  = possibleClosestDist;
        bool buildingComplite = false;
        int  maxSteps         = sizeOfBlock * 4;

        while (!buildingComplite && maxSteps > 0)
        {
            while (currentPontsToProcess.Count > 0)
            {
                // забираем точку для просчёта и работаем с ней
                Point currentPoint = currentPontsToProcess.First.Value;
                currentPontsToProcess.RemoveFirst();


                int currentWayCost = bluprintOfRoadMap[currentPoint.x, currentPoint.y].wayCost;

                // просчитываем верхную точку
                CalculatePoint(descriptor, bluprintOfRoadMap, currentPoint, to, Base.DIREC.DOWN, sizeOfBlock, currentWayCost, ref nodeClosestDist, currentPontsToProcess, nextIterationPontsToProcess);

                // просчитываем нижнюю точку
                CalculatePoint(descriptor, bluprintOfRoadMap, currentPoint, to, Base.DIREC.UP, sizeOfBlock, currentWayCost, ref nodeClosestDist, currentPontsToProcess, nextIterationPontsToProcess);

                // просчитываем левую точку
                CalculatePoint(descriptor, bluprintOfRoadMap, currentPoint, to, Base.DIREC.RIGHT, sizeOfBlock, currentWayCost, ref nodeClosestDist, currentPontsToProcess, nextIterationPontsToProcess);

                // просчитываем правую точку
                CalculatePoint(descriptor, bluprintOfRoadMap, currentPoint, to, Base.DIREC.LEFT, sizeOfBlock, currentWayCost, ref nodeClosestDist, currentPontsToProcess, nextIterationPontsToProcess);
            }


            // принимаем решение о дальнейших итерациях

            WayNode WayNodeFinal = bluprintOfRoadMap[to.x, to.y];
            if (WayNodeFinal.wayCost == possibleClosestDist)
            {
                buildingComplite = true;
            }
            else
            {
                // если мы исчерпали возможности для построения маршрута - завершаем проектирование маршрута
                if (WayNodeFinal.wayCost != WayNode.UNREACHABLE && nextIterationPontsToProcess.Count == 0)
                {
                    buildingComplite = true;
                }
                // в противном случае продолжаем
                else
                {
                    // меняем местами коллекции
                    LinkedList <Point> supportPointer = currentPontsToProcess;
                    currentPontsToProcess       = nextIterationPontsToProcess;
                    nextIterationPontsToProcess = supportPointer;
                }
            }

            maxSteps--;
        }


        if (!buildingComplite)
        {
            Debug.LogError("PrepareBluprintOfRoads: We cann't build way");
            Logger.CreatePathFinderErrorReport(bluprintOfRoadMap, from, to, descriptor.FreeSpaceMap);
        }
        else
        {
            // формируем направления дороги по окончанию работы алгоритма "А star!"
            Point      pointToBuild      = new Point(to);
            WayNode    nodeForBuilding   = null;
            WayNode    finalBuildingNode = bluprintOfRoadMap[from.x, from.y];
            Base.DIREC nextDirection     = Base.DIREC.NO_DIRECTION;

            maxSteps = sizeOfBlock * 4;
            do
            {
                // проверяем координыты
                if (pointToBuild.x < 0 || pointToBuild.x >= sizeOfBlock || pointToBuild.y < 0 || pointToBuild.y >= sizeOfBlock)
                {
                    continue;
                }

                nodeForBuilding = bluprintOfRoadMap[pointToBuild.x, pointToBuild.y];

                // добавляем направления, если надо
                Base.DIREC newDirection = nodeForBuilding.previusRoadDirection;
                if (!nodeForBuilding.approvedDirections.Contains(newDirection))
                {
                    nodeForBuilding.approvedDirections.Add(newDirection);
                }

                if (!nodeForBuilding.approvedDirections.Contains(nextDirection) && nextDirection != Base.DIREC.NO_DIRECTION)
                {
                    nodeForBuilding.approvedDirections.Add(nextDirection);
                }

                // устанавливаем цену дороги
                nodeForBuilding.cellCost = WayNode.ROAD_COST;

                switch (newDirection)
                {
                case Base.DIREC.DOWN:
                    pointToBuild.y--;
                    break;

                case Base.DIREC.UP:
                    pointToBuild.y++;
                    break;

                case Base.DIREC.LEFT:
                    pointToBuild.x--;
                    break;

                case Base.DIREC.RIGHT:
                    pointToBuild.x++;
                    break;

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

                nextDirection = Base.InvertDirection(newDirection);
                maxSteps--;
            } while (nodeForBuilding != finalBuildingNode && maxSteps > 0);
        }
    }
Beispiel #16
0
    /**********************************************************************************/
    // строим дороги внутри блока
    //
    /**********************************************************************************/
    public void BuildRoadInBlock(BlockDescriptor descriptor, int x, int y, int blockSize)
    {
        // проверки параметров
        if (x < 0 || y < 0 || descriptor == null || blockSize < 0)
        {
            Debug.LogError("BuildRoadInBlock: Wrong arguments! " + "x " + x + " y " + y + " blockSize " + blockSize + "descriptor is null? " + (descriptor == null).ToString());
            return;
        }

        // подготавливаем коллекции для работы с дорогами и путями
        List <Point> pointsToConnect = new List <Point>();

        WayNode[,] roadMap = new WayNode[blockSize, blockSize];
        for (int i = 0; i < blockSize; i++)
        {
            for (int z = 0; z < blockSize; z++)
            {
                roadMap[i, z] = new WayNode();
            }
        }

        // добавляем точки дорог к зданиям
        for (int buildingID = 0; buildingID < descriptor.Buildings.Count; buildingID++)
        {
            GameObject         building = descriptor.Buildings[buildingID];
            BuildingController ctr      = building.GetComponent <BuildingController>();

            int xCorInRoadMap = ctr.RoadPoint.x + ctr.GetLocalPosition().x - ctr.XBuildingSize / 2;
            int yCorInRoadMap = ctr.RoadPoint.y + ctr.GetLocalPosition().y - ctr.YBuildingSize / 2;

            pointsToConnect.Add(new Point(xCorInRoadMap, yCorInRoadMap));
            roadMap[xCorInRoadMap, yCorInRoadMap].approvedDirections.Add(Base.DIREC.UP);
            roadMap[xCorInRoadMap, yCorInRoadMap].previusRoadDirection = Base.DIREC.UP;
            roadMap[xCorInRoadMap, yCorInRoadMap].cellCost             = WayNode.ROAD_COST;
        }


        // добавляем все входы в блок, которые надо соеденить
        if (descriptor.RoadConnections[(int)Base.DIREC.DOWN] != ROAD_CONNECTION_STATUS.BLOCKED)
        {
            int xCorInRoadMap = blockSize / 2;
            int yCorInRoadMap = 0;
            pointsToConnect.Add(new Point(xCorInRoadMap, yCorInRoadMap));
            roadMap[xCorInRoadMap, yCorInRoadMap].approvedDirections.Add(Base.DIREC.DOWN);
            roadMap[xCorInRoadMap, yCorInRoadMap].previusRoadDirection = Base.DIREC.DOWN;
            roadMap[xCorInRoadMap, yCorInRoadMap].cellCost             = WayNode.ROAD_COST;
        }

        if (descriptor.RoadConnections[(int)Base.DIREC.UP] != ROAD_CONNECTION_STATUS.BLOCKED)
        {
            int xCorInRoadMap = blockSize / 2;
            int yCorInRoadMap = blockSize - 1;
            pointsToConnect.Add(new Point(xCorInRoadMap, yCorInRoadMap));
            roadMap[xCorInRoadMap, yCorInRoadMap].approvedDirections.Add(Base.DIREC.UP);
            roadMap[xCorInRoadMap, yCorInRoadMap].previusRoadDirection = Base.DIREC.UP;
            roadMap[xCorInRoadMap, yCorInRoadMap].cellCost             = WayNode.ROAD_COST;
        }

        if (descriptor.RoadConnections[(int)Base.DIREC.LEFT] != ROAD_CONNECTION_STATUS.BLOCKED)
        {
            int xCorInRoadMap = 0;
            int yCorInRoadMap = blockSize / 2;
            pointsToConnect.Add(new Point(xCorInRoadMap, yCorInRoadMap));
            roadMap[xCorInRoadMap, yCorInRoadMap].approvedDirections.Add(Base.DIREC.LEFT);
            roadMap[xCorInRoadMap, yCorInRoadMap].previusRoadDirection = Base.DIREC.LEFT;
            roadMap[xCorInRoadMap, yCorInRoadMap].cellCost             = WayNode.ROAD_COST;
        }

        if (descriptor.RoadConnections[(int)Base.DIREC.RIGHT] != ROAD_CONNECTION_STATUS.BLOCKED)
        {
            int xCorInRoadMap = blockSize - 1;
            int yCorInRoadMap = blockSize / 2;
            pointsToConnect.Add(new Point(xCorInRoadMap, yCorInRoadMap));
            roadMap[xCorInRoadMap, yCorInRoadMap].approvedDirections.Add(Base.DIREC.RIGHT);
            roadMap[xCorInRoadMap, yCorInRoadMap].previusRoadDirection = Base.DIREC.RIGHT;
            roadMap[xCorInRoadMap, yCorInRoadMap].cellCost             = WayNode.ROAD_COST;
        }


        // проходим по всем точкам соединения и строим чертёж дороги
        for (int i = 0; i < pointsToConnect.Count; i++)
        {
            Point from = pointsToConnect[i];

            for (int z = i + 1; z < pointsToConnect.Count; z++)
            {
                Point to = pointsToConnect[z];

                // после выбора точки строим дорогу "from - to"
                // подготавливаем чертёж
                PrepareBluprintOfRoads(descriptor, roadMap, from, to, blockSize);

                // обнуляем стоимости путей после каждой итерации построения
                for (int xBuprint = 0; xBuprint < blockSize; xBuprint++)
                {
                    for (int yBuprint = 0; yBuprint < blockSize; yBuprint++)
                    {
                        roadMap[xBuprint, yBuprint].wayCost = WayNode.UNREACHABLE;
                    }
                }
            }
        }


        // строим дорогу
        for (int xBuprint = 0; xBuprint < blockSize; xBuprint++)
        {
            for (int yBuprint = 0; yBuprint < blockSize; yBuprint++)
            {
                List <Base.DIREC> approvedDirection = roadMap[xBuprint, yBuprint].approvedDirections;
                if (approvedDirection.Count != 0)
                {
                    int roadKey = GetRoadKeyFromDirection(approvedDirection);

                    if (!m_roadDictionary.ContainsKey(roadKey))
                    {
                        Debug.LogError("Wrong road generation!");
                    }

                    GameObject roadToInstance = m_roadDictionary[roadKey];

                    // правильные координаты будут выставлены несколькими шагами дальше через localPosition
                    GameObject roadInstance = GameObject.Instantiate(roadToInstance, new Vector3(0.0f, 0.0f, 0.0f), Quaternion.identity) as GameObject;

                    // устанавливаем в родителя
                    roadInstance.transform.SetParent(descriptor.gameObject.transform);
                    roadInstance.transform.localPosition = new Vector3((float)(xBuprint) * Base.SIZE_OF_CELL + Base.HALF_OF_CELL,
                                                                       (float)(yBuprint) * Base.SIZE_OF_CELL + Base.HALF_OF_CELL, 0.0f);

                    // отмечаем данную ячейку как занятую для добавления новых объектов
                    descriptor.FreeSpaceMap[xBuprint, yBuprint] = false;

                    // сохраняем отметку о построенной дороге
                    m_roadObjectMap[xBuprint * x, yBuprint *y] = true;
                }
            }
        }

        // обновляем правила дорог
        UpdateRulesForBlock(x, y, descriptor.RoadConnections);
    }