Perhaps another way to shuffle lerped colors in an array?

Did you solve this?

The error message mostly is displayed when there is a misplaced } or { lines of code are outside any function which is not allowed

I think that you forgot to say void here

Yes, I did. You can see in the most recent code examples above that include both the grid and colorList functions.

1 Like

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

1 Like

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!

1 Like

Ah. Okay, now I understand.

1 Like

Thank you very much for all of your help with this!
Will be applying all I learned in this thread to my next project.

2 Likes

Yeah, you really make fast progress!

Proud!

1 Like

@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.

1 Like

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
//
1 Like

I’ll have a chance to look at this more closely this evening. But at first glance looks like it’ll be fun to parse.
Thank you! :nerd_face:

1 Like

@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
//
1 Like

What I’ve changed

I changed only a few things:

  • 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 readability, good maintainability
  • related : SOLID - Wikipedia

Chrisir

2 Likes

Ah, yes. for the grid!

Understood. :slight_smile:

Okay, that makes sense.

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.

Thank you again!!!

3 Likes

Hello @Chrisir!

I have added the next steps to this sketch.

***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. :slightly_smiling_face:

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
//

Thanks a lot for this!

At the moment I don’t have time.

Maybe somebody else can help?

That’s totally fine!! :slight_smile:
Thanks for tagging another member.

1 Like

I haven’t reviewed this entire thread, but:

One way is to use lerpColors() (search forum) and specify the first and last list color as the same value. Wrap the input with modulo.

I think you can make a new function that uses the old color function

Get 2 arrays and join them with concat() command

I didn’t have time to look at it really