0

I am currently working on implementing the A* Pathfinding algorithm into my snake game. I understand how the algorithm works, the only difficult part is implementing the algorithm. More specifically, I am trying to get the neighboring nodes to the current node on the grid. The reason why I am doing this is because I will then be able to loop through the neighboring nodes (with a list) and check which ones have the lowest g and h costs. I have created a method that loops through a list of x and y coordinates of the neighboring nodes and then I create a new temporary node that holds those coordinates. I then have a by default empty nodeNeighborList that keeps track of all the neighboring nodes. Within the method, the temporary node variable (in method) is then added to the list.

My issue is that when I call this method in the run method, I get a NullPointerException that says the issue comes from where I have added the temporary node.

I get the error at 'game.nodeNeighboursList.add(tempNeighbours);'

Here is my code -

public class Nodes {
private Game game = new Game();
public double h,f;
public int x, y;
public Vector2 vector2;
public Nodes parent;


public Nodes(Vector2 v, double h) {
    this.vector2 = v;
    this.h = h;
}

public int getX() {
    return this.x;
}

public void setX(int x) {
    this.x = x;
}

public int getY() {
    return this.y;
}

public void setY(int y) {
    this.y = y;
}
public int getDistanceFromTarget(int x1, int x2, int y1, int y2) {
    return (int) Math.sqrt(Math.pow(x1-x2, 2) + Math.pow(y1-y2, 2));
}

public Nodes getNeigbouringNodes(Nodes CurrentNode) {
    int[] NeighbourX = {CurrentNode.getX()-20, CurrentNode.getX()+20, CurrentNode.getX(), 
            CurrentNode.getX(),CurrentNode.getX()-20, CurrentNode.getX()+20,CurrentNode.getX()-20,CurrentNode.getX()+20};

    int [] NeighbourY = {CurrentNode.getY(),CurrentNode.getY(),CurrentNode.getY()+20,
            CurrentNode.getY()-20,CurrentNode.getY()-20,CurrentNode.getY()-20,CurrentNode.getY()+20,CurrentNode.getY()+20};

    for(int x = 0 ; x < NeighbourX.length ; x ++) {
        for(int y = 0 ; y < NeighbourY.length; y++) {
            Nodes tempNeighbours = new Nodes(new Vector2(NeighbourX[x],NeighbourY[y]),getDistanceFromTarget(
                    NeighbourX[x],Apple.x,NeighbourY[y],Apple.y));
            game.nodeNeighboursList.add(tempNeighbours);
            return tempNeighbours;
        }
    }
    return null;
}

}

This is my main class, the run method is where the 'getNeibouringNodes()' is called:

private int WIDTH = 800,HEIGHT = 800;
private int nodeMax = 800; 

private ArrayList<Snake>snakeList;
private ArrayList<Apple>appleList;
private ArrayList<Nodes>nodeList;
public ArrayList<Nodes>nodeNeighboursList;

//private Nodes nodes;
private Snake snake;
public Apple apple;
private Vector2 nodeVector;
private Thread thread;
static int ticks = 0;
private Random rx;
private Random ry;
private Nodes node;
private int snakeSizeStart = 5;
private int size = 20;
private final int threadSpeed = 80;
private boolean right=false,left=false,up=false,down=false;
private int applePosScalar;
private int distance;

// look this up, and sorting nodes based on fcost
private Comparator<Nodes> NodeSorter = new Comparator<Nodes>() {
    @Override
    public int compare(Nodes arg0, Nodes arg1) {
        if(arg1.getDistanceFromTarget(arg1.getX(), Apple.x, arg1.getX(), Apple.y) < 
                arg0.getDistanceFromTarget(arg0.getX(), Apple.x, arg0.getY(), Apple.y)) {
            return 1;
        }
        if(arg1.getDistanceFromTarget(arg1.getX(), Apple.x, arg1.getX(), Apple.y) > 
                arg0.getDistanceFromTarget(arg0.getX(), Apple.x, arg0.getY(), Apple.y)) {
            return -1;
        }
        return 0;
    }
};

public void init() {
    this.resize(WIDTH,HEIGHT);
    this.setFocusable(true);
    this.addKeyListener(this);


    rx = new Random();
    ry = new Random();

    applePosScalar = WIDTH/size;
    nodeVector = new Vector2(20,20);
    snake = new Snake(0,0,size);
    apple = new Apple(rx.nextInt(applePosScalar),ry.nextInt(applePosScalar),size);
    //nodes = new Nodes(0,0,0,getDistance(0, Apple.x,0,Apple.y));
    node = new Nodes(nodeVector,getDistance(nodeVector.getX(), Apple.x,nodeVector.getY(),Apple.y));

    nodeList = new ArrayList<Nodes>();
    appleList = new ArrayList<Apple>();
    snakeList = new ArrayList<Snake>();
    nodeNeighboursList = new ArrayList<Nodes>();

    thread = new Thread(this);
    thread.start();

}


public void update(Graphics g) {


    paint(g);


}

public void run() {


    for(;;)  {

        if(snakeList.size() == 0) {
            snake = new Snake(snake.x,snake.y,size);
            snakeList.add(snake);
        }
        snake.moveSnake();
        System.out.println(nodeNeighboursList.size());
        if(right) {
            snake.x++;

        }
        if(left) {
            snake.x--;

        }
        if(down) {
            snake.y--;

        }
        if(up) {
            snake.y++;

        }
        if(snake.x < 0 || snake.x > 39 || snake.y < 0 || snake.y > 39) {
            snakeList = null;
            System.exit(0);

        }

        // continuously add a snake to the list
        snakeList.add(new Snake(snake.x,snake.y,size)); 

        // if the above additions are larger than the snakeSizeStart, then remove a snake object from list
        //Other wise there will be an infinite snake!
        if(snakeList.size() > snakeSizeStart) { 
            snakeList.remove(0);
        }

        for(int i = 1 ; i < snakeList.size() ; i++) {
            if(snakeList.get(0).hitBox().intersects(snakeList.get(i).hitBox())) {
                //System.out.println("sdf");
            }
        }
        if(snake.hitBox().intersects(apple.hitBox())) {
            // add to the snake size, this means that the statement above (snakeList.add(new Snake)) will add a new snake
            snakeSizeStart++; 

            appleList.add(new Apple(rx.nextInt(applePosScalar),ry.nextInt(applePosScalar),size));

        }
        getDistance(snake.x,apple.getX(),snake.y,apple.getY());
        node.getNeigbouringNodes(node); // this is the method that gets the neighboring nodes
        System.out.println("S" + nodeNeighboursList.size()); 
        /*
         I want the method to return the amount of neighboring nodes there are to the current one

        */
        this.repaint();

        try {
            Thread.sleep(threadSpeed);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

If anything is unclear, please do not hesitate to ask as I will gladly clear anything up. I would really appreciate any help I can get! Thank you!

Paco Abato
  • 3,920
  • 4
  • 31
  • 54
  • Is the init() method being executed so creating the nodeNeighboursList object? – Paco Abato Jun 02 '18 at 10:15
  • @PacoAbato yes it says 'nodeNeighboursList = new ArrayList();'. If that is what you mean –  Jun 02 '18 at 10:48
  • I mean if that method is being executed. Put a breakpoint and debug to look out if it stops there, or add a message you can see later so you are sure the code is being executed. – Paco Abato Jun 02 '18 at 10:55
  • @PacoAbato I put a System.out.println("text"); in the init(); method, and nothing was being printed out. However, I did find that changing the nodeNeighboursList to static removed the error. The objective of my method is to return all the adjacent nodes to the node that I have put into the parameters. So if the input node (one in the parameters) has 8 adjacent nodes, then I should have 8 in the list. My issue now is that the list continues to add nodes forever, which is not what I want. Could you help me? –  Jun 02 '18 at 11:16
  • Make the init method private. Call the init method in the constructor of that main class then create a new instance of that main class. – Terran Jun 02 '18 at 12:13
  • @Terran Sorry, but I forgot to mention that the init method is an inherited method from Applet –  Jun 02 '18 at 12:46
  • It's hard to tell whats going on. Probably you're mixing the Runnable of the thread with the class that extends your Applet, which calls init. When you start the thread, it creates a whole new instance of the class without calling init on it. You should move the logic into a separate class that implements Runnable and in the Applet class you only start the thread with that Runnable. e.g. `new Thread(new MyRunnable()).start();` – Terran Jun 03 '18 at 14:13

0 Answers0