ArrayList size gives a nullPointerException, while data is stored

Hi,

I have a problem.

My arraylist called spawns gives a NullPointerException on spawns.size. This happens in the constructor. I tried it with IntLists, but the same thing happened.

The ArrayList should be read here.

class Chicken {

  PVector position;
  PVector velocity;
  PVector acceleration;

  float r;
  float maxSpeed;

  float spawn;

  Chicken() {
    spawn = random(landflock.landscape.spawns.size()); **<--** error happens here. commenting out this bit stops the error
    


    velocity = new PVector (random(-1, 1), random(-1, 1));
    position = new PVector (random(width), random(height));

    //position = new PVector(random(landflock.landscape.spawns.get(int(spawn)).x), random(landflock.landscape.spawns.get(int(spawn)).y));
   <-- it should be used here and the next line.



    acceleration = new PVector (random(-1, 1), random(-1, 1));
    r = 3.0;
    maxSpeed = 3;

  }

}

The ArrayList gets initialised and filled here.

class Landscape {
  float increment = 0.01;

  color water = #4FAECE;
  color sand = #FFD84F;
  color grass = #93B554;
  color rock = #978472;

  color[] colourMap  = {water, sand, grass, rock};

  ArrayList<Walls> walls;

  PImage img;

  //IntList spawnX;
  //IntList spawnY;

  ArrayList<PVector> spawns;   <-- It is made here

  Landscape() {

    walls = new ArrayList<Walls>();

    //spawnX = new IntList();
    //spawnY = new IntList();
    
    spawns = new ArrayList<PVector>();   <-- initialised
    spawns.add(new PVector(0,0));        <-- filling with 1 does not help.
  }

  void buildLandscape() {
    loadPixels();
    float xoff = 0.0; // Start xoff at 0

    noiseDetail(1);

    // For every x,y coordinate in a 2D space, calculate a noise value and produce a brightness value
    for (int x = 0; x < width; x++) {
      xoff += increment;   // Increment xoff 
      float yoff = 0.0;   // For every xoff, start yoff at 0
      for (int y = 0; y < height; y++) {
        yoff += increment; // Increment yoff

        pixels[x+y*width] = colourMap[int(noise(xoff, yoff)*7.5)];

        if ((int(noise(xoff, yoff)*7.5) == 1) || (int(noise(xoff, yoff)*7.5) == 2)) {
          //spawnX.append(x);
          //spawnY.append(y);
          spawns.add(new PVector (x, y));
        }
      }
    }
    updatePixels();
    }
  }

Does anyone have any insights in why this happens and how I can solve this? Is it because it gets called through multiple classes?
I’m just starting with processing, so the knowledge is not always there and it is more following tutorials to understand everything.

Thanks in advance!

Edit:
Full Code
Main Class

LandFlock landflock;

void setup() {
  size (1280, 720);
  frameRate(30);
  landflock = new LandFlock();
  landflock.startUp();
}

void draw() {
  landflock.run();
  for (int p = 0; p < landflock.landscape.walls.size(); p++) {
    landflock.landscape.walls.get(p).displayWalls();
  }
}

Chicken Class

class Chicken {

  PVector position;
  PVector velocity;
  PVector acceleration;

  float r;
  float maxSpeed;

  color chickenBodyColour;
  color chickenHeadColour;

  float spawn;

  Chicken() {
    spawn = random(landflock.landscape.spawns.size()-1);



    velocity = new PVector (random(-1, 1), random(-1, 1));

    //position = new PVector (random(width), random(height));
        position = new PVector(random(landflock.landscape.spawns.get(int(spawn)).x), random(landflock.landscape.spawns.get(int(spawn)).y));



    acceleration = new PVector (random(-1, 1), random(-1, 1));
    r = 3.0;
    maxSpeed = 3;

    chickenBodyColour = #a35638;
    chickenHeadColour = #d92027;
  }


  void render() {
    // Draw a triangle rotated in the direction of velocity
    float theta = velocity.heading() + radians(90);
    stroke(0);
    pushMatrix();
    translate(position.x, position.y);

    rotate(theta);
    fill(chickenBodyColour);
    ellipse(0, 0, 15, 15);
    fill(chickenHeadColour);
    ellipse(0, -9, 7, 7);

    popMatrix();
  }

  // Wraparound
  void borders() {
    if (position.x < -r) position.x = width+r;
    if (position.y < -r) position.y = height+r;
    if (position.x > width+r) position.x = -r;
    if (position.y > height+r) position.y = -r;
  }

  void updatePositionChickens() {
    velocity.add(acceleration);
    velocity.limit(maxSpeed);
    position.add(velocity);
  }
}

Flock Class

class Flock {
  Chicken[] chicken;

  PVector loc;
  PVector vel;
  PVector acc;

  float maxForce = .05;
  float maxSpeed = 3;

  float neighbourDistance = 50;
  float wantedSeperation = 25;


  Flock() {
    chicken = new Chicken[100];
    for (int i = 0; i < chicken.length; i++) {

      chicken[i] = new Chicken ();
    }
  }

  void run() {
    for (int i = 0; i < chicken.length; i++) {

      loc = chicken[i].position;
      vel = chicken[i].velocity;
      acc = chicken[i].acceleration;

      PVector seperate = seperation(chicken);
      PVector align = alignment(chicken);
      PVector cohering = cohesion(chicken);

      //PVector avoidWalls


      seperate.mult(1.2);
      align.mult(1.0);
      cohering.mult(1.0);

      applyForce(seperate);
      applyForce(align);
      applyForce(cohering);

      chicken[i].acceleration = acc;

      chicken[i].updatePositionChickens();
      chicken[i].borders();
      chicken[i].render();

      acc.mult(0);

      println(chicken[10].position);
    }
  }


  void flocking() {
    PVector seperate = seperation(chicken);
    PVector align = alignment(chicken);
    PVector cohering = cohesion(chicken);


    seperate.mult(1.5);
    align.mult(1.0);
    cohering.mult(1.0);

    applyForce(seperate);
    applyForce(align);
    applyForce(cohering);
  }


  void applyForce(PVector force) {
    acc.add(force.mult(10));
  }


  PVector seek(PVector target) {
    PVector wanted = PVector.sub(target, loc);
    wanted.normalize();
    wanted.mult(maxSpeed);

    PVector steer = PVector.sub(wanted, vel);
    steer.limit(maxForce);
    return steer;
  }

  PVector seperation(Chicken[] chicken) {
    PVector steer = new PVector (0, 0);
    int counter = 0;

    for (Chicken other : chicken) {
      float distance = PVector.dist(loc, other.position);

      if ((distance > 0) && (distance < wantedSeperation)) {
        PVector difference = PVector.sub(loc, other.position);
        difference.normalize();
        difference.div(distance);
        steer.add(difference);
        counter++;
      }
    }

    if (counter > 0) {
      steer.div((float)counter);
    }

    if (steer.mag() > 0) {
      steer.normalize();
      steer.mult(maxSpeed);
      steer.sub(vel);
      steer.limit(maxForce);
    }
    return steer;
  }


  PVector alignment(Chicken[] chicken) {
    PVector sum = new PVector(0, 0);
    int counter = 0;

    for (Chicken other : chicken) {
      float distance = PVector.dist(loc, other.position);

      if ((distance > 0) && (distance < neighbourDistance)) {
        sum.add(other.velocity);
        counter++;
      }
    }

    if (counter > 0) {
      sum.div(counter);
      sum.normalize();
      sum.mult(maxSpeed);
      PVector steer = PVector.sub(sum, vel);
      steer.limit(maxForce);
      return steer;
    } else {
      return new PVector(0, 0);
    }
  }


  PVector cohesion(Chicken[] chicken) {
    PVector sum = new PVector(0, 0);
    int counter = 0;

    for (Chicken other : chicken) {
      float distance = PVector.dist(loc, other.position);

      if ((distance > 0) && (distance < neighbourDistance)) {
        sum.add(other.position);
        counter++;
      }
    }

    if (counter > 0) {
      sum.div(counter);
      return seek(sum);  // Steer towards the position
    } else {
      return new PVector(0, 0);
    }
  }

  //PVector avoidWalls() {
  //  PVector steer = new PVector (0, 0);
  //  int counter = 0;

  //  for (int c = 0; c < landflock.landscape.walls.size(); c++) {
  //    float distance = PVector.dist(loc, landflock.landscape.walls.get(c).location);

  //    if ((distance > 0) && (distance < wantedSeperation)) {
  //      PVector difference = PVector.sub(loc, landflock.landscape.walls.get(c).location);
  //      difference.normalize();
  //      difference.div(distance);
  //      steer.add(difference);
  //      counter++;
  //    }
  //  }

  //  if (counter > 0) {
  //    steer.div((float)counter);
  //  }

  //  if (steer.mag() > 0) {
  //    steer.normalize();
  //    steer.mult(maxSpeed);
  //    steer.sub(vel);
  //    steer.limit(maxForce);
  //  }
  //  return steer;
  //}
}

Logic (LandFlock) class

class LandFlock {

  Landscape landscape;
  Flock flock;

  LandFlock() {

    landscape = new Landscape();

    flock = new Flock();
  }


  void startUp() {
    landscape.saveBackground();
  }

  void run() {
    landscape.displayLandscape();
    flock.run();
  }
}

Landscape class

class Landscape { //<>// //<>// //<>//
  float increment = 0.01;

  color water = #4FAECE;
  color sand = #FFD84F;
  color grass = #93B554;
  color rock = #978472;

  color[] colourMap  = {water, sand, grass, rock};

  ArrayList<Walls> walls;

  PImage img;

  //IntList spawnX;
  //IntList spawnY;

  ArrayList<PVector> spawns = new ArrayList<PVector>();

  Landscape() {

    walls = new ArrayList<Walls>();

    //spawnX = new IntList();
    //spawnY = new IntList();

    spawns = new ArrayList();
    spawns.add(new PVector (0, 0));
  }

  void buildLandscape() {
    loadPixels();
    float xoff = 0.0; // Start xoff at 0

    noiseDetail(1);

    // For every x,y coordinate in a 2D space, calculate a noise value and produce a brightness value
    for (int x = 0; x < width; x++) {
      xoff += increment;   // Increment xoff 
      float yoff = 0.0;   // For every xoff, start yoff at 0
      for (int y = 0; y < height; y++) {
        yoff += increment; // Increment yoff

        pixels[x+y*width] = colourMap[int(noise(xoff, yoff)*7.5)];

        if ((int(noise(xoff, yoff)*7.5) == 1) || (int(noise(xoff, yoff)*7.5) == 2)) {
          //spawnX.append(x);
          //spawnY.append(y);
          spawns.add(new PVector (x, y));
        }

        if (
          ((int(noise(xoff, yoff)*7.5) == 0) || (int(noise(xoff, yoff)*7.5) == 3))  
          && (
          (int(noise(xoff - increment, yoff - increment)*7.5) == 1) || 
          (int(noise(xoff - increment, yoff - increment)*7.5) == 2) ||
          (int(noise(xoff, yoff - increment)*7.5) == 1) || 
          (int(noise(xoff, yoff - increment)*7.5) == 2) ||
          (int(noise(xoff + increment, yoff - increment)*7.5) == 1) || 
          (int(noise(xoff + increment, yoff - increment)*7.5) == 2) ||

          (int(noise(xoff - increment, yoff)*7.5) == 1) || 
          (int(noise(xoff - increment, yoff)*7.5) == 2) ||
          (int(noise(xoff + increment, yoff)*7.5) == 1) || 
          (int(noise(xoff + increment, yoff)*7.5) == 2) ||

          (int(noise(xoff - increment, yoff + increment)*7.5) == 1) || 
          (int(noise(xoff - increment, yoff + increment)*7.5) == 2) ||
          (int(noise(xoff, yoff + increment)*7.5) == 1) || 
          (int(noise(xoff, yoff + increment)*7.5) == 2) ||
          (int(noise(xoff + increment, yoff + increment)*7.5) == 1) || 
          (int(noise(xoff + increment, yoff + increment)*7.5) == 2)
          )) {

          walls.add(new Walls(new PVector(x, y)));
        }
      }
    }
    updatePixels();
  }

  void saveBackground() {

    buildLandscape();
    save("background.jpg");
  }

  void displayLandscape() {
    img = loadImage("background.jpg");
    image(img, 0, 0);
  }

  void displayWalls() {
    if (walls.size() > 0) {
      for (int i = 0; i < walls.size(); i++) {
        walls.get(i).displayWalls();
      }
      println("in");
    }
    println("out");
  }
}

Walls class

class Walls {
  PVector location;  

  Walls(PVector loc) {
    location = loc;
  }

  void displayWalls() {
    rectMode(CENTER);
    fill(100);
    rect(location.x, location.y, 1, 1);
    rectMode(CORNER);
  }
}
1 Like

I don’t think landflock exists, does it?

1 Like

Thanks for the quick answer.

I don’t think landflock exists, does it?

I have some more classes. landflock is the name for the class where my logic happens. I need to rename that. In landflock the chicken class and landscape class meet. That is why I called it through landflock.

class LandFlock {

  Landscape landscape;
  Flock flock;

  LandFlock() {

    landscape = new Landscape();

    flock = new Flock();
  }


  void startUp() {
    landscape.saveBackground();
  }

  void run() {
    landscape.displayLandscape();
    flock.run();
  }
}

The Flocking class contains the flocking code for the chickens. I copied most of it from Daniel Schiffman.
If I comment out that 1 line, it works for PVector (random, random), but this 1 line breaks it, without giving squigly lines in Processing.

Also thanks for the comment on size. I changed the generation of the position PVector to spawn-1

Are you instantiating LandFlock?

Yes. In my main class I have this:

LandFlock landflock;

void setup() {
  size (1280, 720);
  frameRate(30);
  landflock = new LandFlock();
  landflock.startUp();
}

void draw() {
  landflock.run();
  for (int p = 0; p < landflock.landscape.walls.size(); p++) {
    landflock.landscape.walls.get(p).displayWalls();
  }
}

I just wanted to say thank you for the time you take to help me.

I don’t have walls, so I created the class (mostly empty/contains an empty method displayWalls()) and I get no errors when I run.

Can you post all your code? Will make debugging it easier …

*Edit … nevermind, I forgot I was instantiating LandFlock() in Chicken()

I just uploaded a zip file with all the code.

If you would rather have it as text, I will update my first post will all code.

edit:
In the chicken class, on line 23 it gives an error. This is solved in the version in the top post. The problem is that it doesn’t even get there.

1 Like

hope this helps … I have pinned down the issue. The object landflock is returning null when called in Chicken().

LandFlock landflock;

void setup() {
  landflock = new LandFlock();

  println("setup " + landflock);
}

void draw() {
}

class Chicken {

  Chicken() {
    //spawn = random(landflock.landscape.spawns.size());

    println(landflock);
  }
}


class Flock {
  Chicken[] chicken;


  Flock() {
    chicken = new Chicken[1];
    for (int i = 0; i < chicken.length; i++) {
      chicken[i] = new Chicken();//
    }
  }
}


class LandFlock {

  Landscape landscape;
  Flock flock;

  LandFlock() {

    flock = new Flock();
    landscape = new Landscape();
  }
}

class Landscape { 

  ArrayList<Walls> walls;

  Landscape() {
    walls = new ArrayList<Walls>();
  }
}

class Walls {
  PVector location;  

  Walls(PVector loc) {
  }   

  void displayWalls() {
  }
}


2 Likes

You have been a saint. It is late here, so I will work on it tomorrow. Thank you very much.

I am sure there is a better way … but in the meantime you could have a method in LandFlock that you call in setup() after you instantiate it that instantiates Flock()

ex …

void setup() {
  landflock = new LandFlock();

  println("setup " + landflock);
  landflock.init();
}

class LandFlock {

  Landscape landscape;
  Flock flock;

  LandFlock() {

    
    landscape = new Landscape();
  }
  
  void init() {
    flock = new Flock();
  }
}
2 Likes

I got it to work using this method.
Thank you for your help and time!

1 Like