Beispiel #1
0
        public static SparseGraph FloodFill(World world, Vector2D startPosition)
        {
            var graph = new SparseGraph(false);

            var firstNode = new NavGraphNode(
                idx: graph.NextNodeIndex,
                position: startPosition
                );

            graph.AddNode(firstNode);

            FloodFill(graph: graph, world: world, node: firstNode);

            return(graph);
        }
        public NavGraphNode FindNearestNode(Vector2D target)
        {
            double       closestDistance = double.MaxValue;
            NavGraphNode nearestNode     = null;

            foreach (var node in NodeList)
            {
                //Reset the IsTarget flag
                node.IsTarget = false;

                var distanceX   = Math.Abs(target.X - node.Position.X);
                var distanceY   = Math.Abs(target.Y - node.Position.Y);
                var distanceSqr = distanceX * distanceY;
                if (distanceSqr < closestDistance)
                {
                    closestDistance = distanceSqr;
                    nearestNode     = node;
                }
            }

            nearestNode.IsTarget = true;
            return(nearestNode);
        }
        public void Render(Graphics g)
        {
            NavGraphNode target = null;

            foreach (NavGraphNode node in NodeList)
            {
                var left = (int)node.Position.X - 2;
                var top  = (int)node.Position.Y - 2;


                if (node.NearbyEntity == ItemType.Grass)
                {
                    g.FillEllipse(new SolidBrush(Color.Green), left - 4, top - 4, 8, 8);
                }
                else
                {
                    g.FillEllipse(new SolidBrush(Color.Black), left, top, 4, 4);
                }

                if (node.IsTarget)
                {
                    target = node;
                }

                foreach (var edge in GetConnectedEdges(node.Index))
                {
                    var nodeTo = GetNode(edge.To);
                    g.DrawLine(new Pen(Color.Black), node.Position.ToPoint(), nodeTo.Position.ToPoint());
                }
            }

            if (target != null)
            {
                g.FillEllipse(new SolidBrush(Color.Red), (int)target.Position.X - 10, (int)target.Position.Y - 10, 20, 20);
            }
        }
Beispiel #4
0
        private static void FloodFill(SparseGraph graph, World world, NavGraphNode node)
        {
            /*
             * This method should create all edges and neighbouring nodes that are possible
             *
             * C:     Current node
             * 1 - 8: Neighbouring nodes for which the edges/nodes should be generated if not colliding with object
             * W:     Width or space between nodes
             *
             *       1 -- 2 -- 3
             *       | \  |  / |
             *       |  \ | /  |
             *       4 -- C -- 5
             *       |  / | \  |
             *       | /  |  \ |
             *       6 -- 7 -- 8
             *
             *
             *  1 (c.X - W, c.Y - W)
             *  2 (c.X    , c.Y - W)
             *  3 (c.X + W, c.Y - W)
             *  4 (c.X - W, c.Y    )
             *  5 (c.X + W, c.Y    )
             *  6 (c.X - W, c.Y + W)
             *  7 (c.X    , c.Y + W)
             *  8 (c.X + W, c.Y + W)
             */


            List <Vector2D> neighbouringPoints = new List <Vector2D>()
            {
                new Vector2D(x: node.Position.X - Width, y: node.Position.Y - Width), // 1
                new Vector2D(x: node.Position.X, y: node.Position.Y - Width),         // 2
                new Vector2D(x: node.Position.X + Width, y: node.Position.Y - Width), // 3

                new Vector2D(x: node.Position.X - Width, y: node.Position.Y),         // 4
                new Vector2D(x: node.Position.X + Width, y: node.Position.Y),         // 5

                new Vector2D(x: node.Position.X - Width, y: node.Position.Y + Width), // 6
                new Vector2D(x: node.Position.X, y: node.Position.Y + Width),         // 7
                new Vector2D(x: node.Position.X + Width, y: node.Position.Y + Width), // 8
            };

            foreach (var point in neighbouringPoints)
            {
                // Do not add node if it collides with obstacle and skip to next node
                var obstacle = IsObjectInRange(obstacles: world.Obstacles, point: point);
                if (obstacle?.Type == ItemType.Block)
                {
                    continue;
                }

                // Also skip this node if it is outside of the world boundaries
                if (point.X < 0 || point.Y < 0 || point.X > world.Width || point.Y > world.Height)
                {
                    continue;
                }

                // Try to get the neighbouring node and create a new node if it doesn't exist
                var neighbour = graph.GetNode(point.X, point.Y) ?? new NavGraphNode(graph.NextNodeIndex, point);

                // If the index is equal to the NextNodeIndex, it means that the node was created here and thus should
                // be added to the graph. If it isn't equal, we got an existing node from the graph earlier.
                var neighbourDidAlreadyExist = neighbour.Index != graph.NextNodeIndex;
                if (!neighbourDidAlreadyExist)
                {
                    graph.AddNode(neighbour);
                }

                // Check if edge exists, and add one if that is not the case
                if (!graph.EdgeList.Exists(x => x.From == node.Index && x.To == neighbour.Index))
                {
                    // But also check if the edge doesn't through an object, otherwise it shouldn't be drawn
                    var obstacleForEdge = IsObjectInRange(
                        obstacles: world.Obstacles,
                        point: new Vector2D(
                            node.Position.X +
                            ((neighbour.Position.X - node.Position.X) /
                             2), // Take the X-coordinate in the middle of the edge
                            node.Position.Y +
                            ((neighbour.Position.Y - node.Position.Y) /
                             2) // Take the Y-coordinate in the middle of the edge
                            ));

                    if (obstacleForEdge == null || obstacleForEdge?.Type != ItemType.Block)
                    {
                        // Add edge in both directions
                        graph.AddEdge(new GraphEdge(from: node.Index, to: neighbour.Index));
                        graph.AddEdge(new GraphEdge(from: neighbour.Index, to: node.Index));
                    }
                }

                // Go on with the neighbour node, if it didn't exist yet, otherwise skip to the next node
                if (neighbourDidAlreadyExist)
                {
                    continue;
                }
                FloodFill(graph: graph, world: world, node: neighbour);
            }
        }
 public void AddNode(NavGraphNode node)
 {
     NodeList.Add(node);
     NextNodeIndex++;
 }