Search code examples
javapath-findinga-star

A* Pathfinding Needs to go around corner, not through them


I have an issue where I would like for the pathfinding to calculate to go around a corner of a "wall", like so:

* []|
[][]|
____|

But as of right now, It cuts the corner through the wall. I cannot remove diagonal movement altogether, I would like the pathfinding to allow for diagonal movement in open areas. As of right now, I can only convince it to not take the corner at all by creating another "wall there." Here is the needed code:

public static void Ai() {
    open.add(grid[startX][startY]);

    Cell current;

    while (true) {
        current = open.poll();
        //If the cell is blocked, move on
        if (current == null)break;
        closed[current.x][current.y] = true;

        //If cell is where you want to end up, stop the loop
        if (current.equals(grid[endX][endY])) {
            return;
        }

        Cell t;
        if(current.x-1>=0){
            t = grid[current.x-1][current.y];
            checkAndUpdateCost(current, t, current.finalCost+V_H_COST); 

            if(current.y-1>=0){                      
                t = grid[current.x-1][current.y-1];
                if (checkAndReturnWall(grid[current.x-1][current.y]) || checkAndReturnWall(grid[current.x][current.y - 1])) {
                    checkAndUpdateCost(current, t, (current.finalCost + DIAGONAL_COST) * 500);
                }
                else checkAndUpdateCost(current, t, current.finalCost+DIAGONAL_COST); 
            }

            if(current.y+1<grid[0].length){
                t = grid[current.x-1][current.y+1];
                if (checkAndReturnWall(grid[current.x-1][current.y]) || checkAndReturnWall(grid[current.x][current.y + 1])) {
                    checkAndUpdateCost(current, t, (current.finalCost + DIAGONAL_COST) * 500);
                }
                else checkAndUpdateCost(current, t, current.finalCost+DIAGONAL_COST); 
            }
        } 

        if(current.y-1>=0){
            t = grid[current.x][current.y-1];
            checkAndUpdateCost(current, t, current.finalCost+V_H_COST); 
        }

        if(current.y+1<grid[0].length){
            t = grid[current.x][current.y+1];
            checkAndUpdateCost(current, t, current.finalCost+V_H_COST); 
        }

        if(current.x+1<grid.length){
            t = grid[current.x+1][current.y];
            checkAndUpdateCost(current, t, current.finalCost+V_H_COST); 

            if(current.y-1>=0){
                t = grid[current.x+1][current.y-1];
                if (checkAndReturnWall(grid[current.x+1][current.y]) || checkAndReturnWall(grid[current.x][current.y - 1])) {
                    checkAndUpdateCost(current, t, (current.finalCost + DIAGONAL_COST) * 500);
                }
                else checkAndUpdateCost(current, t, current.finalCost+DIAGONAL_COST); 
            }

            if(current.y+1<grid[0].length){
               t = grid[current.x+1][current.y+1];
                if (checkAndReturnWall(grid[current.x+1][current.y]) || checkAndReturnWall(grid[current.x][current.y + 1])) {
                    checkAndUpdateCost(current, t, (current.finalCost + DIAGONAL_COST) * 500);
                }
                else checkAndUpdateCost(current, t, current.finalCost+DIAGONAL_COST); 
            }  
        }
    }

Walls are returned as null as cells, checkAndReturnWall returns true when walls are present in the selected cell.


Solution

  • On the assumption that your play field is a square-grid, then you could evaluate the movement as 2-movements (one movement on the x-axis, one movement on the y-axis), then enact it as one. To elaborate:

    You are attempting to move north-east. pardon my pseudocode:

    if(checkEastCell() != wall){
       moveNorthEast();
    }
    else if(checkNorthCell() != wall){
       moveNorthEast();
    }
    else{
       pathingFailure(); 
    }