I’m attempting to create a function to do basic array manipulation. I’d like to pass it an empty array and have the new array returned. I’ve included the code below, but I am not sure how to get it to work correctly.
I was also hoping to get randomly-timed intervals, by resetting the frameCount % value. This function does not seem to be operating correctly either, if anyone has any ideas.
Thanks for the help!
void setup(){
size(640, 480);
background(100, 10, 100);
}
void coord(float [] arr1){
for (int x = 0; x < 20; x++) {
arr1[x] = random(1);
};
};
void draw() {
float [] locArr = new float[20];
int amt=100;
if ((frameCount%amt) == 1)
{
coord(locArr);
amt = int(random(100));
};
println(locArr);
};
The function is working as you want. The problem is that you are re-creating the array as empty each time draw() gets called, so you’re wiping out the values coord() gave you. Move your println() to inside the if() block.
Keep in mind that the default frameCount goes up 60 times per second. You’re spewing out println()s that often.
OK - I might be a little confused here. Let me see if I can break it down.
My goal is to produce a dozen or so different arrays using a “coord” function.
My understanding is that coord does not “return” anything… i.e., if I have something like the following, nested in my draw() function:
locArray = coord();
It will produce a “cannot convert from void to float[]” error.
So, I’m assuming I need to pass some sort of variable into the coord argument, load it with array values, and then use the variable in the rest of the code body.
The issue then, as @scudly poitns out - is that draw() wipes out the array on each frame. This becomes a problem if I need to have access to the arrays outside of this particular if Block.
Maybe I’m still a little hazy on the scope and function aspects of Processing/Java. Apparently, you can’t even pass the variable into an else statement, as the following produces an “locArr cannot be resolved to a variable” error.
void setup(){
size(640, 480);
background(100, 10, 100);
}
void coord(float [] arr1){
for (int x = 0; x < 20; x++) {
arr1[x] = random(1);
};
};
void draw() {
int amt=100;
if ((frameCount%amt) == 1)
{
float [] locArr = new float[20];
coord(locArr);
amt = int(random(100));
}
else {println(locArr);}
};
My next thought was to wrap it in a for loop. This didn’t work either…
void setup(){
size(640, 480);
background(100, 10, 100);
}
void coord(float [] arr1){
for (int x = 0; x < 20; x++) {
arr1[x] = random(1);
};
};
void draw() {
int amt=100;
for (int n = 0; n < 1; n++) {
float [] locArr = new float[20];
if ((frameCount%amt) == 1)
{
coord(locArr);
amt = int(random(100));
}
else {println(locArr);}
};
};
The only question I have remaining is if you wanted to do something like the following, where you wrap a bunch of iterations, in a For Loop, so that you could pull several different random arrays from the same function… my hope was that “arr” would be rewritten for each instance, but now I’m wondering if I need to juggle with something in the void setup().
for ( int n = 0; n < 3; n++) {
for( int i=0; i<20; i++ )
circle( arr[i], height/2, 20 );
}
}
float[] arr;
int amt = 40;
void setup() {
size( 640, 480 );
arr = coord();
}
void draw() {
background(0);
if (frameCount % amt == 0) {
arr = coord();
amt = int(random(1, 100));
}
for ( int i=0; i<20; i++ )
ellipse(arr[i], height/2, 20, 20);
}
// ------------------------------------------------
float[] coord() {
float[] arrResult = new float[20];
for (int i=0; i<20; i++) {
arrResult[i] = random(width);
}
return arrResult;
}
Your question about for-loops
not sure if I understand you here.
remember that the screen is not updated throughout (not inside the for-loops) but only at the end of draw(). Therefore, your nested for loop would not show what you expect.
Instead the approach by scudly is correct: it uses the fact that draw() loops automatically and that it updates the screen at its end. The array gets updated coord( arr ); (“pull several different random arrays from the same function”).
Essentially scudly’s solution is equivalent to your nested for loop, except that the outer for loop is replaced by draw() itself, which loops automatically.
A change Chrisir made but didn’t mention (and that I realized after going to bed last night) is that int(random(100)) returns values from 0 up to 99 which might occasionally give a value of 0 and you can’t compute mod 0. So it’s better to limit the range to random(1, 100).
Even better, there is no reason to use % at all. Just count down each frame and leave frameCount out of it.
But that’s all a side issue to your variable scoping.
Any variable that you declare inside of draw() will get re-declared every frame. If you want anything to persist for more than 1/60 of a second, you have to scope the variable globally. You can call coord() repeatedly and get different sets of randomized arrays, but if you want the results to last, you have to use multiple arrays that are all stored at the global scope – either different variables or an array of arrays.
You can also think of an array of arrays as just one big 1-dimensional array. Fill an array with 60 numbers and just use 20 at a time.
arr = new float[60]; // at the global scope
for( int n=0; n<3; n++ )
for( int i=0; i<20; i++ )
circle( arr[ n*20+i ], height*(n+0.5)/3, 20 );
The main problem with this code is that it assumes that
the parameter arr1 is not null in other words the array exists and
if the array exists it contains at least 20 elements
It would be best if we create a function that avoids both these issues like this
float[] coord(float [] target) {
if (target == null) {
// create the array if it doesn't exit
target = new float[20];
}
for (int x = 0; x < target.length; x++) {
// for each element in the array assign a random number between 0 and 1
target[x] = random(1);
}
return target;
}
If the array does not exist i.e. target == null then it creates a new array otherwise it uses the existing array.
Notice the for loop uses target.length to find the number of elements in an array. This is a safe way to do it.
The following sketch shows it in action. Press ‘n’ key for a new array or ‘e’ key to use an existing array
float[] a = new float[20];
void setup() {
size(640, 480);
}
float[] coord(float [] target) {
if (target == null) {
target = new float[20];
}
for (int x = 0; x < target.length; x++) {
target[x] = random(1);
}
return target;
}
void keyTyped() {
if (key == 'n') { // replace existing array with new with random data
a = coord(null);
}
if (key == 'e') { // populate existing array with new random data
a = coord(a);
}
println("-------------------------------------");
println(a);
}
void draw() {
background(100, 10, 100);
fill(0, 255, 0);
noStroke();
for (int i = 0; i < a.length; i++) {
ellipse((i*20)+20, a[i]*height, 16, 16);
}
}