コード例 #1
0
 public void Tick() //This method should be called by MatchEngine
 {
     for (int i = m_activeTasks.Count - 1; i >= 0; --i)
     {
         PathFinderTask task = m_activeTasks[i];
         Debug.Assert(!task.IsTerminated);
         if (task.CallbackIfCompleted())
         {
             if (!task.IsTerminated && m_activeTasks[i] == task)
             {
                 m_activeTasks.RemoveAt(i);
                 m_idToActiveTask.Remove(task.UnitId);
             }
         }
     }
 }
コード例 #2
0
        public void Find(long unitId, long targetId, IVoxelDataController dataController,
                         Coordinate[] waypoints, Action <long, Coordinate[]> callback, Action <long> terminateCallback)
        {
            if (waypoints == null)
            {
                throw new ArgumentNullException("waypoints");
            }
            PathFinderTask task;

            if (m_idToActiveTask.TryGetValue(unitId, out task))
            {
                task.Terminate();
                m_activeTasks.Remove(task);
            }

            task = new PathFinderTask(dataController.PlayerIndex, unitId, targetId, dataController.Map, dataController.MapSize, dataController.ControlledData, waypoints[0] /*dataController.Coordinate*/, dataController.Abilities, waypoints, m_matrixPools, callback, terminateCallback);
            m_idToActiveTask[unitId] = task;
            m_activeTasks.Add(task);
        }
コード例 #3
0
        private Coordinate GetCoordinate(PathFinderTask task, int row, int col)
        {
            int type   = task.ControlledData.Type;
            int weight = task.ControlledData.Weight;
            int height = task.ControlledData.Height;

            MapCell cell = task.Map.Get(row, col, weight);

            VoxelData target;
            VoxelData beneath = cell.GetDefaultTargetFor(type, weight, task.PlayerIndex, false, out target);

            if (beneath == null)
            {
                return(new Coordinate(row, col, 0, weight));
            }

            int altitude = beneath.Altitude + beneath.Height;

            return(new Coordinate(row, col, altitude, weight));
        }
コード例 #4
0
        private bool TryToMove(bool checkTarget, PathFinderTask task, Coordinate from, Coordinate next, out Coordinate result, out VoxelData resultData)
        {
            resultData = null;

            MapCell cell = task.Map.Get(next.Row, next.Col, next.Weight);

            int type   = task.ControlledData.Type;
            int weight = task.ControlledData.Weight;
            int height = task.ControlledData.Height;

            MapCell targetCell;

            if (checkTarget)
            {
                VoxelData targetData = cell.GetById(task.TargetId);
                if (targetData != null)
                {
                    next.Altitude = targetData.Altitude;
                    CmdResultCode canMove = VoxelDataController.CanMove(task.ControlledData, task.Abilities, task.Map, task.MapSize, from, next, false, false, false, out targetCell);
                    if (canMove == CmdResultCode.Success)
                    {
                        resultData = targetData;
                        result     = next;
                        return(true);
                    }
                }
            }

            //Change altitude if failed with target coordinate
            VoxelData target;
            VoxelData beneath = cell.GetDefaultTargetFor(type, weight, task.PlayerIndex, false, out target);

            if (beneath == null)
            {
                result = from;
                return(false);
            }

            // This will allow bomb movement
            bool isLastStep = task.Waypoints[task.Waypoints.Length - 1].MapPos == next.MapPos;

            if (isLastStep)
            {
                //Try target coordinate first
                next = task.Waypoints[task.Waypoints.Length - 1];

                //last step is param false -> force CanMove to check next coordinate as is
                CmdResultCode canMove = VoxelDataController.CanMove(task.ControlledData, task.Abilities, task.Map, task.MapSize, from, next, false, false, false, out targetCell);
                if (canMove == CmdResultCode.Success)
                {
                    result = next;
                    return(true);
                }
            }

            if (target != beneath) //this will allow bombs to move over spawners
            {
                if (!isLastStep && target != null && !(target.IsCollapsableBy(type, weight) || target.IsAttackableBy(task.ControlledData)))
                {
                    result = from;
                    return(false);
                }
            }

            next.Altitude = beneath.Altitude + beneath.Height;

            //last step param is false -> force CanMove to check next coordinate as is
            CmdResultCode canMoveResult = VoxelDataController.CanMove(task.ControlledData, task.Abilities, task.Map, task.MapSize, from, next, false, false, false, out targetCell);

            if (canMoveResult != CmdResultCode.Success)
            {
                result = from;
                return(false);
            }

            result = next;
            return(true);
        }
コード例 #5
0
        private void CompleteTask(PathFinderTask task, int[,] hopsMatrix, int size)
        {
            Coordinate coord = task.ClosestToGoal;
            int        row   = coord.Row;
            int        col   = coord.Col;

            List <Coordinate> path = new List <Coordinate>();

            path.Add(coord);

            int        minHops  = hopsMatrix[row, col];
            int        minRow   = 0;
            int        minCol   = 0;
            Coordinate minCoord = new Coordinate();

            while (minHops != 0)
            {
                bool canMove = false;
                for (int r = -1; r <= 1; r++)
                {
                    for (int c = -1; c <= 1; c++)
                    {
                        int s = r + c;
                        if (s != -1 && s != 1)
                        {
                            continue;
                        }

                        int prevRow = row + r;
                        int prevCol = col + c;

                        if (prevCol < 0 || prevRow < 0 || prevRow >= size || prevCol >= size)
                        {
                            continue;
                        }

                        int hops = hopsMatrix[prevRow, prevCol];
                        if (hops == (minHops - 1))
                        {
                            Coordinate prevCoord = GetCoordinate(task, prevRow, prevCol);
                            Coordinate modifiedCoord;
                            VoxelData  notUsed;
                            if (TryToMove(false, task, prevCoord, coord, out modifiedCoord, out notUsed)) //possible errors here (yes you were right... infinite loop if try to move failed?
                            {
                                minHops  = hops;
                                minRow   = prevRow;
                                minCol   = prevCol;
                                minCoord = prevCoord;
                                canMove  = true;
                            }
                        }
                    }
                }

                if (!canMove)
                {
                    //if can't move clear path
                    path.Clear();

                    for (int r = -1; r <= 1; r++)
                    {
                        for (int c = -1; c <= 1; c++)
                        {
                            int s = r + c;
                            if (s != -1 && s != 1)
                            {
                                continue;
                            }

                            int prevRow = row + r;
                            int prevCol = col + c;

                            if (prevCol < 0 || prevRow < 0 || prevRow >= size || prevCol >= size)
                            {
                                continue;
                            }

                            int hops = hopsMatrix[prevRow, prevCol];
                            if (hops == (minHops - 1))
                            {
                                //take first appropriate coordinate
                                Coordinate prevCoord = GetCoordinate(task, prevRow, prevCol);
                                minHops  = hops;
                                minRow   = prevRow;
                                minCol   = prevCol;
                                minCoord = prevCoord;
                                canMove  = true;
                                break;
                            }
                        }
                    }
                }

                if (canMove)
                {
                    row   = minRow;
                    col   = minCol;
                    coord = minCoord;

                    path.Add(coord);
                }
                else
                {
                    //if still can't move then something went wrong and infinite loop take place here
                    Debug.LogError("Infinite Loop");
                    break; //we break this loop
                }
            }

            path.Reverse();
            task.SetCompleted(path.ToArray());
        }
コード例 #6
0
        public void Update()
        {
            int batchSize = GameConstants.PathFinderBatchSize;

            while (m_activeTasks.Count > 0)
            {
                int completedTasksCount = 0;
                for (int i = 0; i < m_activeTasks.Count; ++i)
                {
                    PathFinderTask task = m_activeTasks[i];
                    if (task.IsCompleted)
                    {
                        completedTasksCount++;
                        if (m_activeTasks.Count == completedTasksCount)
                        {
                            return;
                        }

                        continue;
                    }

                    if (batchSize == 0)
                    {
                        return;
                    }

                    batchSize--;

                    Coordinate goal = task.Waypoints[task.Waypoints.Length - 1];
                    int[,] hopsMatrix = task.HopsMatrix;
                    int size = hopsMatrix.GetLength(0);

                    if (task.DataQueue.Count > 0)
                    {
                        PathFinderTask.Data current = task.DataQueue.Dequeue();
                        if (current.Coordinate.MapPos == goal.MapPos)
                        {
                            //path found
                            CompleteTask(task, hopsMatrix, size);
                        }
                        else
                        {
                            //searching for path

                            for (int r = -1; r <= 1; r++)
                            {
                                for (int c = -1; c <= 1; c++)
                                {
                                    int s = r + c;
                                    if (s != -1 && s != 1)
                                    {
                                        continue;
                                    }

                                    int        nextHops = current.Hops + 1;
                                    Coordinate next     = current.Coordinate.Add(r, c);

                                    MapPos pos = next.MapPos;
                                    if (pos.Col < 0 || pos.Row < 0 || pos.Col >= size || pos.Row >= size)
                                    {
                                        continue;
                                    }

                                    if (hopsMatrix[pos.Row, pos.Col] <= nextHops)
                                    {
                                        continue;
                                    }

                                    VoxelData targetData;
                                    if (TryToMove(task.HasTarget, task, current.Coordinate, next, out next, out targetData))
                                    {
                                        hopsMatrix[pos.Row, pos.Col] = nextHops;

                                        if (targetData != null)
                                        {
                                            task.ClosestToGoal = next;
                                            task.Waypoints[task.Waypoints.Length - 1] = next;
                                            task.DataQueue.Clear();

                                            c = 2; //break inner for loop;
                                            r = 2; //break outer for loop
                                        }
                                        else
                                        {
                                            int closestDistance = task.ClosestToGoal.MapPos.SqDistanceTo(goal.MapPos);
                                            int distanceToGoal  = pos.SqDistanceTo(goal.MapPos);
                                            if (distanceToGoal < closestDistance)
                                            {
                                                task.ClosestToGoal = next;
                                            }
                                        }
                                        task.DataQueue.Enqueue(new PathFinderTask.Data(next, nextHops));
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        // path was not found

                        CompleteTask(task, hopsMatrix, size);
                    }
                }
            }
        }