0
\$\begingroup\$

I know the A* algorithm but if I have a long range (firing) enemy 20 metres away in 2D-land and I want it be about 3 metres away from its target (aka the player).

Is there an algorithm for choosing an appropriate path and square?

\$\endgroup\$
  • 1
    \$\begingroup\$ This sounds like a pretty conventional pathfinding case, without any exotic requirements. What leads you to believe that A* would not be suitable for this task? \$\endgroup\$ – DMGregory Dec 30 '16 at 20:30
3
\$\begingroup\$

Try pathfinding to the target using A*, then walking along the path until you are within distance.

Alternatively you could check the distance to the target as the pathfinding goal, but this might be slow due to too many distance calculations.

\$\endgroup\$
  • \$\begingroup\$ This is probably more efficient. I think I wasted an hour of my life writing my answer up on my phone ;-) \$\endgroup\$ – JDSweetBeat Dec 31 '16 at 6:18
1
\$\begingroup\$

You could write a function that checks all tiles within the desired range of the player to see if they are moveable, then cache that tile's position. So, some pseudo code:

/* This SHOULD perform a backwards check 
*   from the specified tile to return all walkable tiles between 
*   the specified tile and all tiles the specified distance away.
*/
function GetTilesWithinDistanceOf(Tile tile, int distance) {
    var m_neighbors = new List();
    foreach(Tile neighbor in tile.neighbors) {
        if(neighbor.IsWalkable()) {
            if(distance > 1) {
                m_neighbors.AddAll(GetTilesWithinDistanceOf(neighbor, distance--));

            } else {
                m_neighbors.Add(neighbor);
            }
        }
    }
    return m_neighbors;
}

Then you could run a simple algorithm to determine which of those tiles has the closest location:

function GetClosestInList(List list, Tile closest_to){
    Tile cached = nil;
    foreach(Tile tile in list){
        if(cached == nil){
            cached = tile;
        } else if (tile.DistanceTo(closest_to) < cached.DistanceTo(closest_to)){
            cached = tile;
        }
    }
    return cached;
}

Then perform your main A* pathfinding algorithm on the position:

AStarPathFinder finder = new AStarPathFinder(GetMap());
List tiles_near_target = GetTilesWithinDistanceOf(target, 3);
Tile optimal_tile = GetClosestInList(tiles_near_target);
List path = finder.ComputePath(GetEnemyTiles(), GetPlayerTile());
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.