Array problem with SLIDER VALUE through for loop

I’m new to JS and p5. I was trying to make a slider which controls the number of objects through array and for loop. But I’m facing two problems.

Problem 1.
If the slider value is above 49, it gives this error
“Cannot read property of undefined. Check the line number in error and make sure the variable which is being operated is not undefined.”

I think the array is not taking values above 49 index.

For this slider, createSlider(0,85), slider is supposed to be on 85, but it stays in 49. Here’s the code,

let bubbles = [];

let slider,s;


function setup() {
  createCanvas(700, 600);
  colorMode(HSB,360,100,100,1);
  
  //creating slider
  s = createSlider(0,85);
  
  //adding bubbles with slider value through for loop
  for (let i=0; i < s.value(); i++){
    
    let a = random (width);
    let b = random (height);
    bubbles[i] = new ball (a,b);
  }
 
  //till this 49 index the code runs but not above it
  print (bubbles[49])
}

function draw() {
  background(0);
  
  //showing, moving and bouncing bubbles
  for (let i=0; i < s.value(); i++){
    
    bubbles[i].show();
    bubbles[i].move();
    bubbles[i].bon();
  
  }
}


//bubble class
class ball {
  constructor(x, y) {
    this.x = x;
    this.y = y;
    this.xd = +3;
    this.yd = -5;
  }

  show() {
    noFill();
    stroke(80,50,100,.5);
    strokeWeight(4);
    ellipse(this.x, this.y, 40, 40);
  }

  move() {
    this.x = this.x + random(-5, 5);
    this.y = this.y + random(-6, 6);
  }

  bon() {
    if (this.x > width || this.x < 0) {
      this.x = this.x * -1;
    }
    if (this.y > height || this.y < 0) {
      this.yd = this.y * -1;
    }
  }

}

Problem 2.
If I set an initial value for slider createSlider(0,85,25), the slider doesn’t go above the initial value and shows same error.

let bubbles = [];

let slider,s;


function setup() {
  createCanvas(700, 600);
  colorMode(HSB,360,100,100,1);
  
  
  //creating slider
  s = createSlider(0,85,25);
  
  
  
  //adding bubbles with slider value through for loop
  for (let i=0; i < s.value(); i++){
    
    let a = random (width);
    let b = random (height);
    bubbles[i] = new ball (a,b);
  }
 

}

function draw() {
  background(0);
  
  
  //showing, moving and bouncing bubbles
  for (let i=0; i < s.value(); i++){
    
    bubbles[i].show();
    bubbles[i].move();
    bubbles[i].bon();
  
  }

}


//bubble class
class ball {
  constructor(x, y) {
    this.x = x;
    this.y = y;
    this.xd = +3;
    this.yd = -5;
  }

  show() {
    noFill();
    stroke(80,50,100,.5);
    strokeWeight(4);
    ellipse(this.x, this.y, 40, 40);
  }

  move() {
    this.x = this.x + random(-5, 5);
    this.y = this.y + random(-6, 6);
  }

  bon() {
    if (this.x > width || this.x < 0) {
      this.x = this.x * -1;
    }
    if (this.y > height || this.y < 0) {
      this.yd = this.y * -1;
    }
  }
}

Can anyone please share how to sort it out? Any help is really appreciated.

Problem is in both cases that you initialize the array in setup once and for all

Theoretically you should redefine the array when you change the slider - or extend it

Thanks for the info. Can you please guide how to do the array part then as I’m a newbie?

you need to call this part when the slider value changes.


  //adding bubbles with slider value through for loop
  for (let i=0; i < s.value(); i++) {
    
    let a = random (width);
    let b = random (height);
    bubbles[i] = new ball (a,b);
  }

It’s a bit more tricky because when we actually

  • reduce the number of balls, we remove some
  • increase the number of balls, we add some balls (instead of doing the entire array anew)

More suitable is a ArrayList in this case.

B/c the max number of balls is 85, you’ll have to create 85 balls too:

  // Adding bubbles matching slider's max value through for loop:
  for (let i = 0; i < 85; ++i) {

BtW, the name of a class or constructor function, both in JS & Java, should follow the UpperCase naming convention:

  • bubbles[i] = new ball (a,b);bubbles[i] = new Ball(a, b);
  • class ball {class Ball {
1 Like

Hi,

You can do it this way …

code

Instead of pushing random values as in the code push balls.
And in draw just simply iterate the balls and update/display it…

Cheers
— mnse

PS: sorry, but I’m not able to copy/paste text from p5js editor nor format it from my mobile, hence the link with hopefully readable code … :confused:

3 Likes

When the slider has a max value you can also define as many balls in setup() as the maximum and then let the slider only define how many are visible.

  • That might look nicer because otherwise balls spawn randomly but don’t have a continuous flight path?
2 Likes

Hi @wasif9098,

Now that I’m able to work on my box (not mobile) I’ve integrated my approach for adding/removing bubbles with your code included. This add and remove bubbles on slider changes regarding the slider value.

Cheers
— mnse

PS: Still you need to consider if you want this or as @Chrisir suggested create all bubbles on setup and only display regarding slider value or if you want the approach to add and remove depending the slider value…

let slider;
let bubbles = [];

function setup() {
  createCanvas(700, 600);
  colorMode(HSB,360,100,100,1);  
  slider = createSlider(1, 100, 50);
  slider.input(valuechanged);
  valuechanged();
}

function valuechanged() {
  if (slider.value() < bubbles.length) {
    bubbles.length = slider.value();
  } else if (slider.value() > bubbles.length) {
    while (bubbles.length < slider.value()) {
      let a = random (width);
      let b = random (height);
      bubbles.push(new ball (a,b));
    }
  }
}

function draw() {
  background(0);
  
  //showing, moving and bouncing bubbles
  for (let i=0; i < bubbles.length; i++){
    bubbles[i].show();
    bubbles[i].move();
    bubbles[i].bon();
  }
}

//bubble class
class ball {
  constructor(x, y) {
    this.x = x;
    this.y = y;
    this.xd = +3;
    this.yd = -5;
  }

  show() {
    noFill();
    stroke(80,50,100,.5);
    strokeWeight(4);
    ellipse(this.x, this.y, 40, 40);
  }

  move() {
    this.x = this.x + random(-5, 5);
    this.y = this.y + random(-6, 6);
  }

  bon() {
    if (this.x > width || this.x < 0) {
      this.x = this.x * -1;
    }
    if (this.y > height || this.y < 0) {
      this.yd = this.y * -1;
    }
  }
}
2 Likes

@Chrisir Thanks for replying. Any documentation about ArrayList in p5.js? Would love to know about that then.

1 Like

@mnse Thank you so much for the code. Love this very much supportive community guys! Actually, I don’t have much clear idea how input() works apart from typing which is in p5 reference. your code helped me to understand it.

Btw, I’m learning p5.js to apply as generative branding. I see it’s quite a long journey and requires some other knowledge like html as well. Thanks for all of this guys once again.

Apparently ArrayList is a thing of native processing and not of o5

Anyway, the method that has been shown using push is equal to arraylist’s add() command

2 Likes

Btw @mnse , I’ve just tweaked this little thing. :sweat_smile: Added an equal with greater condition in else if. Now this helped me to get number of bubbles matched to slider value. Earlier, while the slider value was 1, no bubble showed up.

else if (slider.value() >= bubbles.length) {
    while (bubbles.length < slider.value()) {
      let a = random (width);
      let b = random (height);
      bubbles.push(new ball (a,b));
      }
  }

Hi @wasif9098,

you don’t need to change to >=, as my code do already the right thing. :slight_smile:
The issue is in your boundary check (under some positional circumstances) … :wink:

Cheers
— mnse

1 Like