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);
}
}