Search code examples
nullpointerexceptionprocessingselectinput

NullPointer Exception When Using SelectInput()


I am writing a game in Processing 3.x and I am attempting to use the SelectInput(); a method to load in different game save files. However, I kept getting NullPointer Exceptions that I can't fix. I keep trying to run the SelectInput Function BEFORE the loadGame function, but the program crashes anyway. Currently, in the code below, the program errors out at the line that reads as 'columns=splitTokens(rows[1]);'

Any help to get this code working again would be really appreciated.

The Code:

PImage tile1;
PImage tile2;
PImage tile3;
PImage tile4;
PImage tile5;
PImage tile6;
PImage tile7;
PImage tile8;

String input;

String rows[];
String columns[];
int array2D[][];

boolean gameLoaded = false;

void setup() {
  size(600, 600);
  background(0);
  frameRate(30);

  tile1 = loadImage("grass0.png");
  tile2 = loadImage("grass1.png");
  tile3 = loadImage("grass2.png");
  tile4 = loadImage("tile1.png");
  tile5 = loadImage("tile2.png");
  tile6 = loadImage("tree.png");
  tile7 = loadImage("tree2.png");
  tile8 = loadImage("tile2.png");

  selectInput("Select a file to process:", "fileSelected");

  if (gameLoaded == false) {
    //selectInput("Select a file to process:", "fileSelected");
    loadGame();
    gameLoaded = true;
  }
}


void draw() {
  if (gameLoaded == true) {
    for (int a = 0; a < rows.length; a++) {
      for (int b = 0; b < columns.length; b++) {
        if (array2D[a][b] == 1) {
          image(tile1, a * 100, b * 100);
        }
        if (array2D[a][b] == 2) {
          image(tile2, a * 100, b * 100);
        }
        if (array2D[a][b] == 3) {
          image(tile3, a * 100, b * 100);
        }
        if (array2D[a][b] == 4) {
          image(tile4, a * 100, b * 100);
        }
        if (array2D[a][b] == 5) {
          image(tile5, a * 100, b * 100);
        }
        if (array2D[a][b] == 6) {
          image(tile6, a * 100, b * 100);
        }
        if (array2D[a][b] == 7) {
          image(tile7, a * 100, b * 100);
        }
        if (array2D[a][b] == 8) {
          image(tile8, a * 100, b * 100);
        }
      }
    }
  }
}


void loadGame() {
  //rows=loadStrings("file.txt");
  rows = loadStrings(input);

  columns = splitTokens(rows[1]);

  array2D = new int[rows.length][columns.length];

  println("There are " + rows.length + " rows");
  println("There are " + columns.length + " columns");


  for (int a = 0; a < rows.length; a++) {
    columns = splitTokens(rows[a]);

    for (int b = 0; b < columns.length; b++) {
      array2D[a][b] = Integer.parseInt(columns[b]);
    }
  }
}

void fileSelelected(File selection) {
  if (selection == null) {
    println("Nothing was selected, so nothing happens");
  } else {
    input = selection.getAbsolutePath();
    //rows=loadStrings(input);
  }
}


Solution

  • It's easy to read over, but the documentation suggest that the file selector runs on a separate thread. That means that your program doesn't wait until a file is selected and the selectInput-function is finished. Instead it continues processing your code until a file is selected, then the normal processing is interrupted to handle the fileSelected function.

    In your code that means that loadGame() will always run before you even have the chance to select a file. The solution is to create a variable that checks whether a file has been selected.

    At the top of your code create the variable:

    boolean isFileSelected = false;
    

    Before loading the game, check whether a file was selected:

     if (gameLoaded == false && isFileSelected == true) {
        loadGame();
        gameLoaded = true;
      }
    

    When a file is selected, change the variable:

    void fileSelelected(File selection) {
      if (selection == null) {
        println("Nothing was selected, so nothing happens");
      } else {
        input = selection.getAbsolutePath();
        isFileSelected = true;
      }
    }
    

    If it is not yet fully clear, the following script can help understand the concept. As soon as the program starts it will keep printing start until you have selected a file.

    String test = "start";
    
    void setup() {
      selectInput("Select a file to process:", "fileSelected");
    }
    
    void draw(){
       println(test);
    }
    
    void fileSelected(File selection) {
      if (selection == null) {
        println("Window was closed or the user hit cancel.");
      } else {
        println("User selected " + selection.getAbsolutePath());
        test = "test";
      }
    }