Exemplo n.º 1
0
        public static List <VoronoiCell> GeneratePath(List <VoronoiCell> targetCells, List <VoronoiCell> cells, Rectangle limits)
        {
            Stopwatch sw2 = new Stopwatch();

            sw2.Start();

            List <VoronoiCell> pathCells = new List <VoronoiCell>();

            VoronoiCell currentCell = targetCells[0];

            currentCell.CellType = CellType.Path;
            pathCells.Add(currentCell);

            int currentTargetIndex = 0;

            int iterationsLeft = cells.Count;

            do
            {
                int edgeIndex = 0;

                double smallestDist = double.PositiveInfinity;
                for (int i = 0; i < currentCell.Edges.Count; i++)
                {
                    var adjacentCell = currentCell.Edges[i].AdjacentCell(currentCell);
                    if (adjacentCell == null)
                    {
                        continue;
                    }
                    double dist = MathUtils.Distance(adjacentCell.Site.Coord.X, adjacentCell.Site.Coord.Y, targetCells[currentTargetIndex].Site.Coord.X, targetCells[currentTargetIndex].Site.Coord.Y);
                    dist += MathUtils.Distance(adjacentCell.Site.Coord.X, adjacentCell.Site.Coord.Y, currentCell.Site.Coord.X, currentCell.Site.Coord.Y) * 0.5f;
                    //disfavor small edges to prevent generating a very small passage
                    if (Vector2.Distance(currentCell.Edges[i].Point1, currentCell.Edges[i].Point2) < 200.0f)
                    {
                        dist += 1000000;
                    }
                    if (dist < smallestDist)
                    {
                        edgeIndex    = i;
                        smallestDist = dist;
                    }
                }

                currentCell          = currentCell.Edges[edgeIndex].AdjacentCell(currentCell);
                currentCell.CellType = CellType.Path;
                pathCells.Add(currentCell);

                iterationsLeft--;

                if (currentCell == targetCells[currentTargetIndex])
                {
                    currentTargetIndex++;
                    if (currentTargetIndex >= targetCells.Count)
                    {
                        break;
                    }
                }
            } while (currentCell != targetCells[targetCells.Count - 1] && iterationsLeft > 0);


            Debug.WriteLine("gettooclose: " + sw2.ElapsedMilliseconds + " ms");
            sw2.Restart();

            return(pathCells);
        }
Exemplo n.º 2
0
        public static List<VoronoiCell> GeneratePath(
            List<VoronoiCell> targetCells, List<VoronoiCell> cells, List<VoronoiCell>[,] cellGrid, 
            int gridCellSize, Rectangle limits, float wanderAmount = 0.3f, bool mirror = false)
        {
            Stopwatch sw2 = new Stopwatch();
            sw2.Start();

            //how heavily the path "steers" towards the endpoint
            //lower values will cause the path to "wander" more, higher will make it head straight to the end
            wanderAmount = MathHelper.Clamp(wanderAmount, 0.0f, 1.0f);

            List<GraphEdge> allowedEdges = new List<GraphEdge>();
            List<VoronoiCell> pathCells = new List<VoronoiCell>();
            
            VoronoiCell currentCell = targetCells[0];
            currentCell.CellType = CellType.Path;
            pathCells.Add(currentCell);

            int currentTargetIndex = 1;

            int iterationsLeft = cells.Count;

            do
            {
                int edgeIndex = 0;

                allowedEdges.Clear();
                foreach (GraphEdge edge in currentCell.Edges)
                {
                    var adjacentCell = edge.AdjacentCell(currentCell);
                    if (limits.Contains(adjacentCell.Site.Coord.X, adjacentCell.Site.Coord.Y))
                    {
                        allowedEdges.Add(edge);
                    }
                }

                //steer towards target
                if (Rand.Range(0.0f, 1.0f, Rand.RandSync.Server) > wanderAmount || allowedEdges.Count == 0)
                {
                    double smallestDist = double.PositiveInfinity;
                    for (int i = 0; i < currentCell.Edges.Count; i++)
                    {
                        var adjacentCell = currentCell.Edges[i].AdjacentCell(currentCell);
                        double dist = MathUtils.Distance(
                            adjacentCell.Site.Coord.X, adjacentCell.Site.Coord.Y,
                            targetCells[currentTargetIndex].Site.Coord.X, targetCells[currentTargetIndex].Site.Coord.Y);
                        if (dist < smallestDist)
                        {
                            edgeIndex = i;
                            smallestDist = dist;
                        }
                    }
                }
                //choose random edge (ignoring ones where the adjacent cell is outside limits)
                else
                {
                    edgeIndex = Rand.Int(allowedEdges.Count, Rand.RandSync.Server);
                    if (mirror && edgeIndex > 0) edgeIndex = allowedEdges.Count - edgeIndex;
                    edgeIndex = currentCell.Edges.IndexOf(allowedEdges[edgeIndex]);
                }

                currentCell = currentCell.Edges[edgeIndex].AdjacentCell(currentCell);
                currentCell.CellType = CellType.Path;
                pathCells.Add(currentCell);

                iterationsLeft--;

                if (currentCell == targetCells[currentTargetIndex])
                {
                    currentTargetIndex += 1;
                    if (currentTargetIndex >= targetCells.Count) break;
                }

            } while (currentCell != targetCells[targetCells.Count - 1] && iterationsLeft > 0);


            Debug.WriteLine("gettooclose: " + sw2.ElapsedMilliseconds + " ms");
            sw2.Restart();

            return pathCells;
        }
Exemplo n.º 3
0
        public static List <VoronoiCell> GeneratePath(List <VoronoiCell> targetCells, List <VoronoiCell> cells)
        {
            Stopwatch sw2 = new Stopwatch();

            sw2.Start();

            List <VoronoiCell> pathCells = new List <VoronoiCell>();

            if (targetCells.Count == 0)
            {
                return(pathCells);
            }

            VoronoiCell currentCell = targetCells[0];

            currentCell.CellType = CellType.Path;
            pathCells.Add(currentCell);

            int currentTargetIndex = 0;

            int iterationsLeft = cells.Count / 2;

            do
            {
                int edgeIndex = 0;

                double smallestDist = double.PositiveInfinity;
                for (int i = 0; i < currentCell.Edges.Count; i++)
                {
                    var adjacentCell = currentCell.Edges[i].AdjacentCell(currentCell);
                    if (adjacentCell == null)
                    {
                        continue;
                    }
                    double dist = MathUtils.Distance(adjacentCell.Site.Coord.X, adjacentCell.Site.Coord.Y, targetCells[currentTargetIndex].Site.Coord.X, targetCells[currentTargetIndex].Site.Coord.Y);
                    dist += MathUtils.Distance(adjacentCell.Site.Coord.X, adjacentCell.Site.Coord.Y, currentCell.Site.Coord.X, currentCell.Site.Coord.Y) * 0.5f;

                    //disfavor short edges to prevent generating a very small passage
                    if (Vector2.DistanceSquared(currentCell.Edges[i].Point1, currentCell.Edges[i].Point2) < 150.0f * 150.0f)
                    {
                        //divide by the number of times the current cell has been used
                        //  prevents the path from getting "stuck" (jumping back and forth between adjacent cells)
                        //  if there's no other way to the destination than going through a short edge
                        dist *= 10.0f / Math.Max(pathCells.Count(c => c == currentCell), 1.0f);
                    }
                    if (dist < smallestDist)
                    {
                        edgeIndex    = i;
                        smallestDist = dist;
                    }
                }

                currentCell          = currentCell.Edges[edgeIndex].AdjacentCell(currentCell);
                currentCell.CellType = CellType.Path;
                pathCells.Add(currentCell);

                iterationsLeft--;

                if (currentCell == targetCells[currentTargetIndex])
                {
                    currentTargetIndex++;
                    if (currentTargetIndex >= targetCells.Count)
                    {
                        break;
                    }
                }
            } while (currentCell != targetCells[targetCells.Count - 1] && iterationsLeft > 0);


            Debug.WriteLine("gettooclose: " + sw2.ElapsedMilliseconds + " ms");
            sw2.Restart();

            return(pathCells);
        }