Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Change A* implementation to use a Grid interface #8

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

buddhisthead
Copy link

@buddhisthead buddhisthead commented Oct 11, 2019

Here is a small change to support existing games and non-square grids (namely, hexes). It also allows very large "grid" systems that can't store their costs in a static array. For example, I am building an open world editing tool, which stores a sparse representation of a hex "grid"; using the Grid array would be force eager evaluation of the entire world. This PR allows a lazy fetch of Nodes and also the concrete Neighbors can return hex directions instead of just orthogonal ones. For hexes, the implementation can convert to "offset" coordinates and still use x,y indexing in the existing library.

Here is a copy of my lazy hexes implementation...

    //==========================================================
    // Implement the GridI interface for A* pathfinding library
    //==========================================================

    // Node cache
    Dictionary<(int, int), Node> NodeCache;

    public void PrepareForPathFinding(Pathfinding.DistanceType distance)
    {
        NodeCache = new Dictionary<(int, int), Node> ();
    }

    public Node GetNode (int x, int y)
    {
        Node node = null;
        // Lookup node in cache
        NodeCache.TryGetValue ((x, y), out node);
        if (node == null) {
            // Not there. Create a new one with tile cost based on terrain type, otherw
            TileValue tileValue = overworldMap.GetTileValue (x, y);
            node = new Node (true, x, y); // default cost = 1.0
            if (tileValue.Type == TileType.TTerrain) {
                TerrainType tt = (TerrainType)tileValue.Value;
                SpriteMapItem spriteItem = TerrainTileSetProvider.getSpriteItem (tt.group, tt.index);
                if (spriteItem != null) {
                    node.price = spriteItem.cost;
                }
            }
            // Put new node in cache
            NodeCache.Add ((x, y), node);
        }
        return node;
    }

    public IEnumerable<Node> GetNeighbours (Node currentNode, Pathfinding.DistanceType distance)
    {
        Hex hex = new Hex (currentNode.gridX, currentNode.gridY);
        List<Hex> spaces = hex.Neighbors (1);
        foreach (Hex space in spaces) {
            Node node = GetNode(space.col, space.row);
            yield return node;
        }
        yield return null;
    }

…g to existing grid systems

* Change Form1 to use interface GridI
* Separate interface to a different file
/// The grid supplies Nodes which mark tiles with traversal costs.
/// The grid can be square or hexagonal (using offset coordinate system).
/// </summary>
public interface GridI {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not call it IGrid?

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants