예제 #1
0
        public void StartIntegrationFieldCreation(Tile destinationTile, List <List <int> > areasAndSectorsParam,
                                                  FlowFieldPath flowPathParam, SearchPathJob pathJob, int key, bool pathEdit)
        {
            FlowFieldPath      flowPath        = null;
            bool               aPathIsCreated  = false;
            List <List <int> > areasAndSectors = areasAndSectorsParam;

            List <int>         areas   = new List <int>();
            List <List <int> > sectors = new List <List <int> >();

            Dictionary <IntVector2, List <Tile> > areaConnectionTiles = new Dictionary <IntVector2, List <Tile> >();

            bool firstWorldArea = !pathEdit;

            for (int a = 0; a < areasAndSectors.Count; a++) // each separate search //areasAndSectors.Count
            {
                var firstWorldAreaOfNewSearch = true;

                var index = 0;
                areas.Clear();
                sectors.Clear();
                Dictionary <IntVector2, int[]> alreadyFilledInSector = null;
                IntVector2 areaSectorKey = new IntVector2(0, 0); //area.index, sectorIndex);


                if (pathEdit && flowPathParam != null)
                {
                    flowPath = flowPathParam;
                }

                //setup/starting point of the sectors- and areas-  lists
                int startIndex;
                if (a == 0 && !pathEdit) // first search
                {
                    startIndex = 0;
                    areas.Add(areasAndSectors[a][0]);
                    sectors.Add(new List <int>());
                }
                else // we start with a search that is not the first one. we might be able to skip a lot of already integrated sectors
                {
                    if (flowPath == null)
                    {
                        flowPath = WorldData.FlowFieldManager.FlowFieldPaths[
                            WorldData.FlowFieldManager.FlowFieldPaths.Count - 1];
                    }

                    alreadyFilledInSector = flowPath.IntegrationField.Field;
                    startIndex            = -1;

                    for (int i = 0; i < areasAndSectors[a].Count; i += 2)
                    {
                        areaSectorKey.X = areasAndSectors[a][i];
                        areaSectorKey.Y = areasAndSectors[a][i + 1];

                        if (!alreadyFilledInSector.ContainsKey(areaSectorKey)) // sector not yet filled in
                        {
                            startIndex = i;
                            areas.Add(areasAndSectors[a][startIndex]);
                            sectors.Add(new List <int>());
                            break;
                        }
                    }
                }


                // if -1 we can skip it all
                if (startIndex != -1) // else entire path already calculated by a different search
                {
                    // set what tiles to cross over during a search

                    // separate areas and sectors in arrays
                    for (int i = startIndex; i < areasAndSectors[a].Count; i += 2)
                    {
                        areaSectorKey.X = areasAndSectors[a][i];
                        areaSectorKey.Y = areasAndSectors[a][i + 1];

                        if (areasAndSectors[a][i] == areas[index])
                        {
                            sectors[index].Add(areasAndSectors[a][i + 1]);
                        }
                        else
                        {
                            index++;
                            areas.Add(areasAndSectors[a][i]);
                            sectors.Add(new List <int>());
                            sectors[index].Add(areasAndSectors[a][i + 1]);
                        }

                        if (alreadyFilledInSector != null && alreadyFilledInSector.ContainsKey(areaSectorKey)
                            ) // added sector already filled in
                        {
                            // a couple of sectors where not already found, then they were, then they aren't again
                            // we split up this search, so that every search in the flowing steps is a list of sectors that all directly connect.
                            // no gaps of already filled in sectors
                            areasAndSectors.Add(new List <int>());
                            for (int j = i; j < areasAndSectors[a].Count; j++)
                            {
                                areasAndSectors[areasAndSectors.Count - 1].Add(areasAndSectors[a][j]);
                            }

                            break;
                        }
                    }


                    if (!firstWorldArea &&
                        areasAndSectors[a][startIndex] != areasAndSectors[a][startIndex - 2]) // different world areas
                    {
                        firstWorldAreaOfNewSearch = false;
                    }

                    // going through our areas- and sectors- lists
                    for (int i = 0; i < areas.Count; i++)
                    {
                        WorldData.MultiLevelSectorManager.SetSearchFields(areas[i], sectors[i], true);
                        WorldArea currentWorldArea = WorldData.WorldAreas[areas[i]];

                        if (firstWorldAreaOfNewSearch)
                        {
                            _openSet.Clear();

                            List <Tile> oldSectorTiles = new List <Tile>();

                            if (firstWorldArea)
                            {
                                _tilesSearchList.Add(destinationTile);
                                _tilesSearchList[0].IntegrationValue = 0;
                            }
                            else
                            {
                                WorldArea        area  = WorldData.WorldAreas[areasAndSectors[a][startIndex]];
                                MultiLevelSector start = area.SectorGrid[0][areasAndSectors[a][startIndex - 1]];
                                MultiLevelSector next  = area.SectorGrid[0][areasAndSectors[a][startIndex + 1]];
                                oldSectorTiles =
                                    WorldData.MultiLevelSectorManager.RowBetweenSectorsWithinWorldArea(start, next,
                                                                                                       area);

                                if (pathEdit) // put old values back in the old tiles
                                {
                                    IntVector2 oldTileKey = new IntVector2();
                                    foreach (Tile tile in oldSectorTiles)
                                    {
                                        oldTileKey.X          = tile.WorldAreaIndex;
                                        oldTileKey.Y          = tile.SectorIndex;
                                        tile.IntegrationValue =
                                            flowPath.IntegrationField.Field[oldTileKey][tile.IndexWithinSector];
                                    }
                                }

                                _tilesSearchList.AddRange(oldSectorTiles);
                            }


                            foreach (Tile oldTile in oldSectorTiles)
                            {
                                _closedSet.Remove(oldTile);
                            }
                        }
                        else
                        {
                            WorldArea previousWorldArea;
                            int       lastSectorOfPreviousWorldArea;

                            if (i == 0) // previous world area is not in array, removed because of already covered
                            {
                                previousWorldArea             = WorldData.WorldAreas[areasAndSectors[a][startIndex - 2]];
                                lastSectorOfPreviousWorldArea = areasAndSectors[a][startIndex - 1];
                            }
                            else
                            {
                                previousWorldArea             = WorldData.WorldAreas[areas[i - 1]];
                                lastSectorOfPreviousWorldArea = sectors[i - 1][sectors[i - 1].Count - 1];
                            }

                            int sectorOfCurrentArea = sectors[i][0];


                            IntVector2 areaConnectionKey =
                                new IntVector2(currentWorldArea.Index, previousWorldArea.Index);
                            if (!areaConnectionTiles.ContainsKey(areaConnectionKey))
                            {
                                areaConnectionTiles.Add(areaConnectionKey, new List <Tile>());
                            }

                            List <Tile> tiles = SwitchToNextWorldArea(previousWorldArea, currentWorldArea,
                                                                      lastSectorOfPreviousWorldArea, sectorOfCurrentArea, flowPath);

                            areaConnectionTiles[areaConnectionKey].AddRange(tiles);
                        }

                        WaveExpansionSearchTiles(currentWorldArea);

                        _closedSetFinish.AddRange(_closedSet);

                        // all integration fields generated, create flow field
                        if (firstWorldArea)
                        {
                            aPathIsCreated = true;
                            WorldData.FlowFieldManager.CreateFlowFieldPath(_closedSet, sectors[i], areas,
                                                                           destinationTile, currentWorldArea, key);
                        }
                        else
                        {
                            WorldData.FlowFieldManager.AddToFlowFieldPath(_closedSet, sectors[i], currentWorldArea);

                            if (pathEdit)
                            {
                                aPathIsCreated = true;
                            }
                        }


                        _closedSet.Clear();

                        firstWorldAreaOfNewSearch = false;
                        firstWorldArea            = false;

                        WorldData.MultiLevelSectorManager.SetSearchFields(areas[i], sectors[i], false);
                    }
                }
            }


            if (flowPath == null && WorldData.FlowFieldManager.FlowFieldPaths.Count > 0)
            {
                flowPath = WorldData.FlowFieldManager.FlowFieldPaths[
                    WorldData.FlowFieldManager.FlowFieldPaths.Count - 1];
            }


            if (flowPath != null)
            {
                flowPath.FlowField.FillFlowField(_closedSetFinish, WorldData);
                WorldData.FlowFieldManager.AddAreaTilesToFlowFieldPath(areaConnectionTiles);
            }


            if (pathJob != null)
            {
                pathJob.PathCreated(aPathIsCreated ? flowPath : null, false);
            }
            else
            {
                if (aPathIsCreated)
                {
                    if (flowPath != null)
                    {
                        WorldData.Pathfinder.PathCreated(flowPath, flowPath.Key, pathEdit);
                    }
                }
                else
                {
                    WorldData.Pathfinder.PathCreated(null, 0, pathEdit);
                }
            }

            ResetTilesAfterSearch();
        }
예제 #2
0
 public int GetDirBetweenVectors(IntVector2 start, IntVector2 end)
 {
     if (start == end)
     {
         return(0);
     }
     else
     {
         if (start.x == end.x)
         {
             if (end.y > start.y)
             {
                 return(2);
             }
             else
             {
                 return(1);
             }
         }
         else
         {
             if (end.x > start.x)
             {
                 if (end.y > start.y)
                 {
                     return(5);
                 }
                 else
                 {
                     if (end.y < start.y)
                     {
                         return(4);
                     }
                     else
                     {
                         return(3);
                     }
                 }
             }
             else
             {
                 if (end.x < start.x)
                 {
                     if (end.y > start.y)
                     {
                         return(8);
                     }
                     else
                     {
                         if (end.y < start.y)
                         {
                             return(7);
                         }
                         else
                         {
                             return(6);
                         }
                     }
                 }
                 else
                 {
                     return(0);
                 }
             }
         }
     }
 }