sfml path finding in csharp

Here's an example of using SFML to display a map of nodes and connect them with lines based on an A* pathfinding algorithm in C#:

main.cs
using SFML.Graphics;
using SFML.System;
using SFML.Window;
using System;
using System.Collections.Generic;

namespace SFMLPathfinding
{
    class Node
    {
        public Vector2f Position { get; set; }
        public List<Node> Neighbors { get; set; }
        public float G { get; set; }
        public float H { get; set; }
        public float F { get { return G + H; } }
        public Node CameFrom { get; set; }
        public bool IsObstacle { get; set; }

        public Node(Vector2f position)
        {
            Position = position;
            Neighbors = new List<Node>();
            G = float.MaxValue;
            H = float.MaxValue;
            CameFrom = null;
            IsObstacle = false;
        }
    }

    class Program
    {
        static int mapSize = 20;
        static int nodeSize = 30;
        static RenderWindow window;
        static List<Node> nodes = new List<Node>();
        static List<Node> path = new List<Node>();

        static void Main(string[] args)
        {
            window = new RenderWindow(new VideoMode(mapSize * nodeSize, mapSize * nodeSize), "SFML Pathfinding");
            window.Closed += WindowClosed;

            // Generate the map with nodes
            GenerateNodes();

            // Connect the neighboring nodes
            ConnectNeighbors();

            // Set some random obstacles
            SetObstacles();

            // Calculate the path between two nodes
            CalculatePath(nodes[0], nodes[nodes.Count - 1]);

            while (window.IsOpen)
            {
                window.DispatchEvents();

                window.Clear(Color.White);

                // Draw the nodes and connections
                DrawNodes();
                DrawConnections();

                // Draw the path
                DrawPath();

                window.Display();
            }
        }

        static void GenerateNodes()
        {
            for (int y = 0; y < mapSize; y++)
            {
                for (int x = 0; x < mapSize; x++)
                {
                    Vector2f position = new Vector2f(x * nodeSize, y * nodeSize);
                    Node node = new Node(position);
                    nodes.Add(node);
                }
            }
        }

        static void ConnectNeighbors()
        {
            foreach (Node node in nodes)
            {
                int x = (int)(node.Position.X / nodeSize);
                int y = (int)(node.Position.Y / nodeSize);

                for (int ny = y - 1; ny <= y + 1; ny++)
                {
                    for (int nx = x - 1; nx <= x + 1; nx++)
                    {
                        if (nx >= 0 && ny >= 0 && nx < mapSize && ny < mapSize && (nx != x || ny != y))
                        {
                            Node neighbor = nodes[ny * mapSize + nx];
                            node.Neighbors.Add(neighbor);
                        }
                    }
                }
            }
        }

        static void SetObstacles()
        {
            Random random = new Random();

            for (int i = 0; i < nodes.Count / 3; i++)
            {
                int index = random.Next(0, nodes.Count);
                nodes[index].IsObstacle = true;
            }
        }

        static void CalculatePath(Node startNode, Node goalNode)
        {
            List<Node> openSet = new List<Node>();
            List<Node> closedSet = new List<Node>();

            startNode.G = 0;
            startNode.H = Heuristic(startNode, goalNode);
            openSet.Add(startNode);

            while (openSet.Count > 0)
            {
                Node current = GetLowestF(openSet);

                if (current == goalNode)
                {
                    // Found the path
                    path.Clear();
                    Node node = current;
                    while (node != null)
                    {
                        path.Add(node);
                        node = node.CameFrom;
                    }
                    path.Reverse();
                    return;
                }

                openSet.Remove(current);
                closedSet.Add(current);

                foreach (Node neighbor in current.Neighbors)
                {
                    if (closedSet.Contains(neighbor) || neighbor.IsObstacle)
                    {
                        // Ignore this neighbor
                        continue;
                    }

                    float tentativeGScore = current.G + Distance(current, neighbor);

                    if (!openSet.Contains(neighbor))
                    {
                        openSet.Add(neighbor);
                    }
                    else if (tentativeGScore >= neighbor.G)
                    {
                        // This path is worse than the previous path
                        continue;
                    }

                    neighbor.CameFrom = current;
                    neighbor.G = tentativeGScore;
                    neighbor.H = Heuristic(neighbor, goalNode);
                }
            }
        }

        static Node GetLowestF(List<Node> nodes)
        {
            Node lowest = nodes[0];
            foreach (Node node in nodes)
            {
                if (node.F < lowest.F)
                {
                    lowest = node;
                }
            }
            return lowest;
        }

        static float Distance(Node node1, Node node2)
        {
            return (float)Math.Sqrt(Math.Pow(node1.Position.X - node2.Position.X, 2) + Math.Pow(node1.Position.Y - node2.Position.Y, 2));
        }

        static float Heuristic(Node node1, Node node2)
        {
            // Manhattan distance
            return Math.Abs(node1.Position.X - node2.Position.X) + Math.Abs(node1.Position.Y - node2.Position.Y);
        }

        static void DrawNodes()
        {
            foreach (Node node in nodes)
            {
                CircleShape circle = new CircleShape(nodeSize / 2);
                circle.Origin = new Vector2f(nodeSize / 2, nodeSize / 2);
                circle.Position = node.Position;

                if (node.IsObstacle)
                {
                    circle.FillColor = new Color(139, 139, 139);
                }
                else
                {
                    circle.FillColor = new Color(221, 221, 221);
                }

                window.Draw(circle);
            }
        }

        static void DrawConnections()
        {
            foreach (Node node in nodes)
            {
                foreach (Node neighbor in node.Neighbors)
                {
                    if (!node.IsObstacle && !neighbor.IsObstacle)
                    {
                        VertexArray line = new VertexArray(PrimitiveType.Lines, 2);
                        line[0] = new Vertex(node.Position, Color.Black);
                        line[1] = new Vertex(neighbor.Position, Color.Black);
                        window.Draw(line);
                    }
                }
            }
        }

        static void DrawPath()
        {
            VertexArray pathLine = new VertexArray(PrimitiveType.LinesStrip, (uint)path.Count);

            for (int i = 0; i < path.Count; i++)
            {
                pathLine[(uint)i] = new Vertex(path[i].Position, Color.Red);
            }

            window.Draw(pathLine);
        }

        private static void WindowClosed(object sender, EventArgs e)
        {
            RenderWindow window = (RenderWindow)sender;
            window.Close();
            Environment.Exit(0);
        }
    }
}
7647 chars
256 lines

This code generates a map of nodes, connects their neighboring nodes, and calculates a path between the start and goal nodes. It also includes random obstacles and displays the resulting path using SFML.

gistlibby LogSnag