sfml enemy path finding in csharp

Here's an example of how to implement pathfinding for an enemy in SFML using C#:

First, you need to define the graph for the tiles on which the enemy can move. This can be represented as a 2D grid where each tile is a node in the graph. For example:

main.cs
public class Tile
{
    public int X { get; set; }
    public int Y { get; set; }
    public bool IsPassable { get; set; }
}

public static class GameMap
{
    public static int Width = 10;
    public static int Height = 10;

    public static Tile[,] Tiles = new Tile[Width, Height];

    // Initialize the tile grid and set passable/impassable tiles
    public static void InitMap()
    {
        for (int x = 0; x < Width; x++)
        {
            for (int y = 0; y < Height; y++)
            {
                Tiles[x, y] = new Tile() { X = x, Y = y, IsPassable = true };
            }
        }

        Tiles[3, 5].IsPassable = false;
        Tiles[4, 5].IsPassable = false;
        Tiles[5, 5].IsPassable = false;
    }
}
731 chars
31 lines

Next, you need to define the algorithm for finding the shortest path between two nodes in the graph. One popular algorithm for this is A* (pronounced "A-star"). Here's an example implementation:

main.cs
public class AStarPathfinder
{
    // Compute the Manhattan distance between two tiles
    private int ComputeDistance(Tile a, Tile b)
    {
        return Math.Abs(a.X - b.X) + Math.Abs(a.Y - b.Y);
    }

    // Find the shortest path between start and end tiles
    public List<Tile> FindPath(Tile start, Tile end)
    {
        // Initialize data structures
        SortedSet<Tile> openSet = new SortedSet<Tile>(Comparer<Tile>.Create((a, b) =>
        {
            int f1 = a.G + a.H;
            int f2 = b.G + b.H;

            if (f1 == f2)
            {
                return a.H.CompareTo(b.H);
            }

            return f1.CompareTo(f2);
        }));

        Dictionary<Tile, Tile> cameFrom = new Dictionary<Tile, Tile>();
        Dictionary<Tile, int> gScore = new Dictionary<Tile, int>();
        Dictionary<Tile, int> fScore = new Dictionary<Tile, int>();

        openSet.Add(start);
        gScore[start] = 0;
        fScore[start] = ComputeDistance(start, end);

        // Run A*
        while (openSet.Count > 0)
        {
            var current = openSet.First();

            if (current == end)
            {
                return ReconstructPath(cameFrom, end);
            }

            openSet.Remove(current);

            foreach (var neighbor in GetNeighbors(current))
            {
                if (!neighbor.IsPassable)
                {
                    continue;
                }

                int tentativeGScore = gScore[current] + ComputeDistance(current, neighbor);

                if (!gScore.ContainsKey(neighbor) || tentativeGScore < gScore[neighbor])
                {
                    cameFrom[neighbor] = current;
                    gScore[neighbor] = tentativeGScore;
                    fScore[neighbor] = tentativeGScore + ComputeDistance(neighbor, end);

                    if (!openSet.Contains(neighbor))
                    {
                        openSet.Add(neighbor);
                    }
                }
            }
        }

        return null;
    }

    // Reconstruct the path from the start tile to the end tile
    private List<Tile> ReconstructPath(Dictionary<Tile, Tile> cameFrom, Tile current)
    {
        List<Tile> path = new List<Tile>() { current };

        while (cameFrom.ContainsKey(current))
        {
            current = cameFrom[current];
            path.Insert(0, current);
        }

        return path;
    }

    // Get the list of passable neighbor tiles for a given tile
    private List<Tile> GetNeighbors(Tile tile)
    {
        List<Tile> neighbors = new List<Tile>();

        if (tile.X > 0)
        {
            neighbors.Add(GameMap.Tiles[tile.X - 1, tile.Y]);
        }

        if (tile.X < GameMap.Width - 1)
        {
            neighbors.Add(GameMap.Tiles[tile.X + 1, tile.Y]);
        }

        if (tile.Y > 0)
        {
            neighbors.Add(GameMap.Tiles[tile.X, tile.Y - 1]);
        }

        if (tile.Y < GameMap.Height - 1)
        {
            neighbors.Add(GameMap.Tiles[tile.X, tile.Y + 1]);
        }

        return neighbors;
    }
}
3091 chars
114 lines

Finally, you can use the pathfinding algorithm to move the enemy towards its target. Here's an example implementation:

main.cs
public class Enemy
{
    public int X { get; set; }
    public int Y { get; set; }

    public void MoveTowards(Tile target)
    {
        var pathfinder = new AStarPathfinder();

        var path = pathfinder.FindPath(GameMap.Tiles[X, Y], target);

        if (path == null)
        {
            return;
        }

        if (path.Count > 1)
        {
            X = path[1].X;
            Y = path[1].Y;
        }
    }
}
427 chars
24 lines

With these functions in place, you can call the MoveTowards function on your enemy object to move it towards its target tile. For example, if you want your enemy to move towards the player's position, you can pass in the player's tile as the target:

main.cs
var enemy = new Enemy();
var playerTile = GameMap.Tiles[playerX, playerY];

enemy.MoveTowards(playerTile);
107 chars
5 lines

gistlibby LogSnag