ArrayList issue?

#1

I have this Female class that has an array of coordinates, the move() method adds those coordinates to the Female’s location every tick to move the object etc. etc. My issue is that I have an arrayList full of these objects who have all been given a random set of move coordinates post-construction, BUT are all moving in the exact same pattern even as I log the value of their velocity and can plainly see that they’re all different (sorry for all the currently dead variables):

ArrayList<Female> females = new ArrayList<Female>();
void setup() {
  size(600, 600);
  PVector location = new PVector(height/2, width/2);
  
  for(int i = 0; i < 50; i++){
   int[] colours = {floor(random(255)), floor(random(255)), floor(random(255))};
   Female newFem = new Female(location, "female", 1, colours, 16, 10, 10, 10, 10, 50);
   for(int x = 0; x < newFem.moves.length; x++){
     newFem.moves[x] = new PVector(random(-0.5, 0.5), random(-0.5,0.5));
   }
   females.add(newFem);
  }
  noStroke();
}
void draw() {
  background(255);
  for(int i = 0; i < females.size()-1; i++){
   females.get(i).move();
   females.get(i).display();
  }
}

//Breeder entity object

class Ent{
  ////Abstract properties
  int id;
  int age;
  //'male' or 'female'
  String gender;
  //PVectors
  PVector location;
  PVector velocity = new PVector();
  //n pixels per frame
  float speed;
  
  ////Physical properties
  //0-255
  int[] colour;
  //4, 8, 16
  int size;
  
  ////Combat properties
  float hp;
  float damage;
  float b_velocity;
  float f_rate;
  
  ////Hunger
  boolean hungry = false;
  int hunger = 0;
  int hungermax;

  Ent(PVector location_, String gender_, float speed_, int[] colour_, int size_, float hp_, float damage_, float b_velocity_, float f_rate_){
   id = floor(random(10000000, 99999999));
   location = location_;
   gender = gender_;
   speed = speed_;
   colour = colour_;
   size = size_;
   hp = hp_;
   damage = damage_;
   b_velocity = b_velocity_;
   f_rate = f_rate_;
  }
  
  Ent(){}
  
  //void move(){    
  //  location.add(velocity.x * speed, velocity.y * speed);
  //} 
  //Draw Ent on step
  void display(){
    fill(colour[0], colour[1], colour[2]);
   //Wall wrap
    if(location.y > height){
      location.y = 0.00;
      println("more than height");
    }
    if(location.y < 0){
      location.y = height;
      println("less than height");
    }
    if(location.x > width){
      location.x = 0.00;
    }
    if(location.x < 0){
     location.x = width; 
    }
    rect(location.x, location.y, size, size, 5.00);
  }
  
}



class Female extends Ent{
  
 boolean pregnant = false;
 int gestation = 0;
 int gestperiod;
 PVector[] moves = new PVector[90];

 int food;
 ////Movement
 //increment 
 int stepcount = 0;
 //change direction when stepcount is a modulus of stepchange
 int stepchange;
 //which move is it up to
 int movenumber = 0;
 
   Female(PVector location_, String gender_, float speed_, int[] colour_, int size_, float hp_, float damage_, float b_velocity_, float f_rate_, int gestperiod_){
    super(location_, gender_, speed_, colour_, size_, hp_, damage_, b_velocity_, f_rate_);
    gestperiod = gestperiod_;
    stepchange = floor(random(50, 100));
   }
   
   void move(){
       if(stepcount % stepchange == 0){
         velocity.set(moves[movenumber]);
         println(moves[movenumber].x);
         println(velocity);
         println(stepchange);
         movenumber++;
         if(movenumber == 90){
           movenumber = 0;
         }
       }
       location.add(velocity);
       stepcount++;
   }
   
}
1 Like
#2

if start at random location it looks good??

ArrayList<Female> females = new ArrayList<Female>();
PVector location;

void setup() {
  size(600, 600);
//  PVector location = new PVector(height/2, width/2);

  for (int i = 0; i < 50; i++) {
    location = new PVector(random(width), random(height));
    int[] colours = {floor(random(255)), floor(random(255)), floor(random(255))};
    Female newFem = new Female(location, "female", 1, colours, 16, 10, 10, 10, 10, 50);
    for (int x = 0; x < newFem.moves.length; x++) {
      newFem.moves[x] = new PVector(random(-0.5, 0.5), random(-0.5, 0.5));
    }
    females.add(newFem);
  }
  noStroke();
}
void draw() {
  background(255);
  for (int i = 0; i < females.size()-1; i++) {
    females.get(i).move();
    females.get(i).display();
  }
}

1 Like
#3

Yeah… you’re right. doesn’t really make sense though lol.

#4

You need to put your PVector “location” inside the for loop. Not sure why but it solves your issue.

#5

Hi,

The problem is that all your Female objects are sharing the same location.

When you do that:

PVector location = new PVector(height/2, width/2);
  
for(int i = 0; i < 50; i++){
  ...
  Female newFem = new Female(location, "female", 1, colours, 16, 10, 10, 10, 10, 50);
  ...
...

You are passing the location variable as a reference. It is not a coy of the location PVector but the object itself.
So when a Female object update the values of her own location she is actually changing the value of that one location PVector that all the Female objects share. As a result they all move the same.

There are 2 ways of solving your problem.

Either in he Ent constructor:

Ent(PVector location_, ...) {
  ...
  location = new PVector(location_.x, location_.y);
  ...
}

Or directly where you give the argument:

Female newFem = new Female(new PVector(location.x, location.y), ...);

In both case a new object is created so they no longer share the same location.

4 Likes
#6

That makes perfect sense, thanks heaps friend :slight_smile: