Gotoloop was referring to me saying that the function is portable/ re-usable in another sketch. It’s not because it uses variables from the sketch (from its global level). (The array size)
To make it portable we need to pass this information as a parameter to the function
Yes. That was the problem. Along with placing the color[]listColors = getColorList() in the function for void makeOneRow(). Once I did those two things it worked!
@Chrisir
Well, I appreciate your saying that but I could only get so far with books and youtube videos (as good as they are). The catalyst has been this forum. And your very clear explanations have been extremely helpful.
here is a version where the grid is returned as a result of the function
/* !!! grid made with a grid function AND listColors function !!!*/
// global array
Cell[] cellsGlobal;
void setup() {
size (1400, 800);
cellsGlobal = getGrid(16);
}//func
void draw() {
background (51);
for (Cell currentCell : cellsGlobal) {
currentCell.display();
}//for
}//func
//-----------------------------------------------------------------------------------------
// Tools
Cell[] getGrid(int howMany) {
Cell[] cellsLocal = new Cell[howMany];
color[] listColors = getColorList(cellsLocal.length);
int x = 20, y = x;
int w = (width-40) / cellsLocal.length, h = height-40;
for (int i = 0; i < cellsLocal.length; i++) {
cellsLocal[i] = new Cell(x+i*w, y,
w, h, listColors[i]);
}
return cellsLocal;
}//func
color[] getColorList( int howMany ) {
// for the command lerpColor:
color from = color(random(255), random(255), random(255)); // Start
color to = color(random(255), random(255), random(255)); // End
float step = 1.0f / (howMany-1); // **must use a float number to return a float number**
// stores list of colors
IntList colorIntList = new IntList(howMany);
// for loop to generate an IntList of lerped colors in order
for (int k = 0; k < howMany; k++) {
colorIntList.set(k, lerpColor (from, to, k*step));
}
// this step randomly shuffles the list inventory
colorIntList.shuffle();
// returns the shuffled colors
// as an array
return colorIntList.array();
}//func
//////////////////// CLASS ////////////////////
class Cell {
float x, y,
w, h;
color clr;
// constr
Cell (
float tempX, float tempY,
float tempW, float tempH,
color tempClr) {
x = tempX;
y = tempY;
w = tempW;
h = tempH;
clr = tempClr;
}// constr
void display() {
stroke(255);
fill(clr);
rect(x, y,
w, h);
}//method
//
}//class
//
@Chrisir Hello!
I feel I have a general understanding of what is happening with this new syntax. However, I’ve placed comments next to / beneath lines where I have questions. Or notes on what I think(?) is happening at certain steps. Though am probably off the mark…
By the way, the larger sketch size is nice!!
// *** GRID IS RETURNED via the function: Cell[] getGrid(int howMany) ***
// global array
Cell[] cellsGlobal; // declare the array
void setup() {
size (1400, 800);
cellsGlobal = getGrid(16); //initialize the array
}//func
void draw() {
background (51);
for (Cell currentCell : cellsGlobal) { // alternate syntax for for loop; currentCell is a temporary name while iterating through each element in array
currentCell.display();
// reference states "this structure is easier to iterate over each element of an array"
// ??? Why is this easier? The syntax is easier to read? Or some different reason ? The program loops in a faster way?
}//for
}//func
//-----------------------------------------------------------------------------------------
// Tools
Cell[] getGrid(int howMany) { // *int howMany* is the arguments for # of cells == this addresses the portability issue GoToLoop referred to
Cell[] cellsLocal = new Cell[howMany];
// cellsLocal = local variable for the Cell? makes the function portable
// the number of cells to be created (16 initialized in setup)
color[] listColors = getColorList(cellsLocal.length);
// number of colors matches number of cells in grid
int x = 20, y = x; // local variables to construct the grid
int w = (width-40) / cellsLocal.length, h = height-40; // local variables to construct the grid
for (int i = 0; i < cellsLocal.length; i++) { // iterative loop
cellsLocal[i] = new Cell(x+i*w, y,
w, h, listColors[i]);
}
return cellsLocal; // returns the ?????
// ???? How does *cellsLocal* loop back
// to *currentCell.display()* in draw function ?
// Is the connection to “Cell”?
}//func
color[] getColorList(int howMany) {
// ??? *int howMany* argument is needed here
// for portability, re GoToLoop
color from = color(random(255), random(255), random(255));
color to = color(random(255), random(255), random(255));
float step = 1.0f / (howMany-1);
IntList colorIntList = new IntList(howMany);
// re: *colorIntList* name, previously used *inventory* as the name;
// confirming better to use descriptive names and not the generic *inventory* ???
for (int k = 0; k < howMany; k++) {
colorIntList.set(k, lerpColor (from, to, k*step));
}
colorIntList.shuffle();
return colorIntList.array();
}//func
///////////// CLASS /////////////
class Cell {
float x, y,
w, h;
color clr;
// constr
Cell (
float tempX, float tempY,
float tempW, float tempH,
color tempClr) {
x = tempX;
y = tempY;
w = tempW;
h = tempH;
clr = tempClr;
}// constr
void display() {
stroke(255);
fill(clr);
rect(x, y,
w, h);
}//method
//
}//class
//
The function Cell[] getGrid is now returning the grid as a result. Accordingly the line that receives the result is cellsGlobal = getGrid(16); in setup().
I used a simplified for-loop: for (Cell currentCell : cellsGlobal) {
Your questions
The for loop in draw() is simplified.
Yes. It’s better readable. It’s not faster I guess.
cellsLocal = local variable/array for the grid.
Please note that I use width and height here now.
This means that the function would change the cell size automatically when you change the window size (using the size() command in the function setup()).
The function getGrid() is now returning the grid as a result.
So cellsLocal is made in the function and returned as a result of the function (using return command).
In setup() the array gets copied (by the = sign) into the global grid cellsGlobal.
The line currentCell.display() is within the for loop which reads: for each element in the array cellsGlobal copy the element into currentCell and use this in currentCell.display().
So here two aspects are at work: the grid is returned and the for-loop uses the global grid.
Yes.
confirmed. You can choose the name freely. A correct, descriptive name is an important part of good programming.
What is good programming?
A correct, descriptive name of variables, objects and arrays… is an important part of good programming.
Convention: constants are ALL_CAPITAL, classes StartWithCapital, objects startSmall, lists are in plural (containing many objects or elements)
Using functions to modularize your code is also part of good programming. Good naming of functions too.
Not too long functions. Functions longer than one screen could be considered as being too long and could be split up in 2 smaller functions.
The idea of portability (no dependencies) is also part of good programming. Re-usability
Using classes / OOP is part of good programming.
Good comments are part of good programming. Not explaining a command but rather the purpose of a section / function.
Good programming has the goal that a co-worker of you (or yourself after 6 months) has a chance to understand the code quickly and can work from it to a new bigger project. When he reads “inventory” he wouldn’t understand as much as when reading colorIntList.
Good to know! I guess I read the reference too literally sometimes. Still working out the language that must be used vs the generic – in this case “inventory”…
The What is good programming? bullet list at the end is GREAT!! Thank you!!
I have 2 more directions I’d like to explore with this sketch. So will likely post a follow up with new added code within the next couple of days, if you’re curious to take a look.
***Please note comments that begin in TOOLS area starting with the function color[]getThreeColorLerp() {
As a way to add more user control over the colors generated, I’ve added a third color to the mix.
I still need to add a step where the end color lerps to the start color. So that when I create a new function (see next line below) the colors will undulate seamlessly.
I want to now build a new list array via a new function expandColorArrayLength() from the colors generated in getThreeColorLerp() function so that this core group of colors is repeated. This array index size would have at least 100 spots but could be easily increased or decreased.
I would then apply this repeating color array to a large grid with both columns and rows.
There are a couple of questions commented in the expandColorArrayLength() function section regarding how to proceed.
Thank you for this link!! I read it with interest.
MAIN ///////////////////////////////////////
// global array
Cell[] cellsGlobal; // declare the array
void setup() {
size (1000, 600);
cellsGlobal = getGrid(15); //initialize the array
}//func
void draw() {
background (51);
for (Cell currentCell : cellsGlobal) {
currentCell.display();
}//for
// rectangles placed for color reference
// to confirm target colors are hit when color is lerped
fill(color(12, 187, 229));
rect(width-150, 0, 150, 50);
fill(color (250, 200, 63));
rect((width/2)-75, 0, 150, 50);
fill(color (245, 17, 48));
rect(0, 0, 150, 50);
}//func
//-----------------------------------------------------------------------------------------
// Tools
Cell[] getGrid(int howMany) {
Cell[] cellsLocal = new Cell[howMany];
color[] listColors = getThreeColorLerp();
// local variables to construct the grid
int x = 25, y = x; // local variables to construct the grid
int w = (width-40) / cellsLocal.length, h = height-50;
for (int i = 0; i < cellsLocal.length; i++) { // iterative loop
cellsLocal[i] = new Cell(x+i*w, y,
w, h, listColors[i]);
}
return cellsLocal;
}//func
color[]getThreeColorLerp() { // no parameter now b/c next step
// is to *make copies of the colorGroup_1 array and combine* to make
// a longer array with at least 100 places
color start = color (245, 17, 48);
color midpoint = color (250, 200, 63);
//color midpoint = color (255); // test for gradation to white
color end = color(12, 187, 229);
int num = 15;
float step = 1.0f / num;
IntList colorGroup_1 = new IntList (num);
// iterative loop for lerpColor using 3 colors
for (int k = 0; k < num; k++) {
float m = map (step, 0.0, 1.0, 0.0, 2.0);
// used map and if and else to determine transition
// point from 2nd to 3rd color
if (k*m <= 1.0) {
colorGroup_1.set (k, lerpColor(start, midpoint, k*m));
} else {
colorGroup_1.set (k, lerpColor(midpoint, end, (k*m)-0.9));
}
}
return colorGroup_1.array();
}
//color [] expandColorArrayLength(){
// this function is to take IntList colorGroup_1
// generated in getThreeColorLerp() function and
// copy colorGroup_1 multiple times and place in
// a new expanded array containing at least 100 index spots
// Possible to do with a for loop using modulo to loop back to zero index?
// Or is there a better way?
// Duplicate the array and use concat()? Though this seems less straightforward ...
//color[] listColors = getThreeColorLerp();
//}
CLASS //////////////////////////
class Cell {
float x, y,
w, h;
color clr;
// constr
Cell (
float tempX, float tempY,
float tempW, float tempH, color tempClr)
{
x = tempX;
y = tempY;
w = tempW;
h = tempH;
clr = tempClr;
}// constr
void display() {
stroke(0);
fill(clr);
rect(x, y,
w, h);
}//method
//
}//class
//