2D grid array question

For the past few days have been trying to better understand grids and arrays.
After reading D Shiffman tutorial on 2D grid arrays I am now trying to play with that code a bit.

  • I would like the grid(s) to appear twice, one above the other.
  • I have placed alpha in the fill so to be able to see thru to the grid below.
  • However, I see only one instance of the grid.
  • Why do I not see both grids?
Cell[][] grid;

// Number of columns and rows in the grid
int cols = 10;
int rows = 8;

void setup() {
  size(600, 600);
  grid = new Cell[cols][rows];
  for (int i = 0; i < cols; i++) {
    for (int j = 0; j < rows; j++) {
      // Initialize each object
      grid[i][j] = new Cell(i*(width/5), j*(height/8), width/5, height/8); // why does this grid not appear?
      grid[i][j] = new Cell(i*(width/10), j*(height/8), width/10, height/8);
    }
  }
}

void draw() {
  background(255);

  for (int i = 0; i < cols; i++) {
    for (int j = 0; j < rows; j++) {

      grid[i][j].display();
      grid[i][j].display();
    }
  }
  fill (125, 30); 
  rect (50, 50, 150, 150); ///// this is a test rectangle with gray fill and 30 alpha tranparency
}

// A Cell object
class Cell {

  float x, y;   // x,y location
  float w, h;   // width and height

  // Cell Constructor
  Cell (float tempX, float tempY, float tempW, float tempH) {
    x = tempX;
    y = tempY;
    w = tempW;
    h = tempH;
  } 

  void display() {

    stroke(0);
    fill(125, 30); // gray with 30 alpha for transparency 
    rect(x, y, w, h);
  }
}

you are showing the same grid twice.

and the first definition of the grid is overwritten by the second definition.

with your current Cell code you would need
grid1
grid2
to do that.

2 Likes

Ah, that makes sense!! I’ll make the corrections.
Thank you @kll :grinning:

1 Like

You have only one grid and you overwrite it.

To achieve this you could name the 2nd grid grid2.

BUT having 2 grids doesn’t have to do with 2D grid. In fact before you work with 2 2D grids you should first appreciate working with ONE 2D grid. It would exactly look the same as your 1D grid from your last sketch but the data are ordered now in a way that is also like a grid internally (grid instead of list).

The advantage of a 2D grid is for example that you can find the neighbor cells of a cell much easier. Just add 1 or -1 to cell index x and y. [x+1][y]

Try this in a new sketch with only one 2D array and move a selected cell over the grid with cursor keys. (seleted cell wanders over the grid). Or make it so that when you click on a cell all 9 neighboring cells get selected. That’s easier in 2D array although it looks the same on the screen as your 1D array from the previous sketch.

In your case, the 1D array (list) looks the same on the screen like the 2D array (grid). This is because you have given the objects in the list screen positions that arrange them in a grid. With a 2D array the data internally looks more like on the screen, because a grid has a column and a row number for each data (cell).

Explanation

But internally they are different: the data is stored differently.

  • For a list you need only one value to retrieve the entry of one line/cell (line number 4: list[3] (counting starts with 0); 3 is the index for the array)

  • For a 2D array you need 2 numbers to get to a cell, x and y position of the cell in the array (not on screen) like grid[3] [5] gives you the data in column 4 and row 6. Think of a chess board where we also say e2 (it’s like saying 5,2) or think of an Excel sheet (calculation program by Microsoft)

Example for a grid

Let’s say your program holds data for 10 students, and each has name, surname, address, age.

In a list that would be difficult.

In a grid, you would have one line per student and in the columns the data for her like name, surname, address, age. To retrieve the age of student #2 you’d check the cell 3,3 (counting starts with 0).

Each data is retrieved by passing it two indexes (think of a chess board with rows and columns). Each data is a String or a number or a color.

A grid looks something like this:


-----------
|   0|    1|
-----------
|   2|    3|
-----------
|   0|    1|
-----------
|   2|    3|
-----------

Chrisir

1 Like

@Chrisir Thank you so much for such a clear explanation!!! :grinning: :grinning: :grinning:
This opens up so many possibilities going forward (which I guess is the point).
I now feel confident moving on to next step — converting my 1D grid sketch to 2D.

1 Like

Great!

Did you look at the tutorial?

If you’re referring to Shiffman text tutorial, I have found and read it.
Thank you again!

1 Like

I have now converted the 1D grid to a 2D grid.

I renamed some variables so as to simplify for ease in possible future adjustments / consistency.

However, I have commented in sketch one question regarding grid shift. As it appears the 2D grid and 1D grid require different counter-solutions for the rectMode(CENTER).

The current interactivity is as desired. But my question, is this the BEST or most efficient solution? Or is there another conventional way?
Before I add any more interactivity I want to make sure all is as should be.
Thank you!!

/////////////////////////////////////////////

// 2D Grid Array of Button objects
Button [][] myButtons;

// Number of columns and rows in the grid
int num = 7;
int cols = num, rows = cols;

int r = int(random(255));
int g = int(random(255));
int b = int(random(255));

color background = color (r, g, b);

void setup() {
  size(800, 800);
  
  //int x = 40 + 50, y = x, // this 1D grid shift no longer works when 
                            // shifting 2D grid as a unit to the right + down 50 px

  myButtons = new Button[cols][rows];
  for (int i = 0; i < cols; i++) {
    for (int j = 0; j < rows; j++) {
      // Initialize each object
      myButtons[i][j] = new Button (i*(width/cols), j*(height/rows), 
        color (random(255), random(255), random(255)), // random colors
        color (random(255), random(255), random(255)), // new random colors when mouseOver
        random(50, 125)); // random sizes
    }
  }
}

void draw() {

  background(background);

  translate((width/cols)/2, (width/rows)/2); // along with pushMatrix + popMatrix, this is the only way 
                     // I could get the 2D grid to shift as a unit. And then + adjustment 
                     // in mouseOver function in Button class. Is this correct approach?
  pushMatrix();
  
  for (int i = 0; i < cols; i++) {
    for (int j = 0; j < rows; j++) {
      myButtons[i][j].mouseOver();
      myButtons[i][j].display();
    }
  }
  popMatrix();
}
void mouseClicked() { 

  background = color(random(255), random(255), random(255));
}

////////////////////////////////////////

class Button {
  float x, y;
  color colRect;
  color colRect2;

  float sz;
  boolean off = true; // button starts in OFF position

  Button ( 
    float tempX, float tempY, 
    color tempColor, color tempColor2, float tempSz) {

    x = tempX;
    y = tempY;

    colRect = tempColor;
    colRect2 = tempColor2;

    sz = tempSz;
  }

  void display() {
    if (off) {
      fill (colRect);
      noStroke();
    } else {
      fill (colRect2);
      noStroke();
    }

    rectMode(CENTER);
    rect(x, y, sz, sz);
  }

  void mouseOver() {

    if (mouseX > x - sz/2 +(width/cols)/2  && 
      mouseX < x + sz/2 +(width/cols)/2  &&
      mouseY > y - sz/2 +(width/rows)/2  &&
      mouseY < y + sz/2 +(width/rows)/2 ) {

      off = false;
    } else {
      off = true;
    }
  }
}

This

int r = int(random(255));
int g = int(random(255));
int b = int(random(255));


color background = color (r, g, b);

shorter

color background = color (random(255), random(255), random(255));

grid position

You don’t shift the grid as a whole but each cell.

You didn’t use x,y in setup()

int x = 58, y = x;

Now I have

 // Initialize each object
      myButtons[i][j] = new Button (x+ i*(width/cols), y+ j*(height/rows), // USE x and y here

Then get rid of translate, pushMatrix and popMatrix


void draw() {
  background(background);

  for (int i = 0; i < cols; i++) {
    for (int j = 0; j < rows; j++) {
      myButtons[i][j].mouseOver();
      myButtons[i][j].display();
    }
  }
}

and adjust mouseOver()


  if (mouseX > x - sz/2 && 
      mouseX < x + sz/2  &&
      mouseY > y - sz/2  &&
      mouseY < y + sz/2  ) {

Chrisir

1 Like

Hello @Chrisir
Much to my chagrin, I thought this was going to be a lot easier.
My thinking is to create a function in the CLASS and name it: move().
Then use the dot syntax in draw() as I did with mouseOver().

I’ve tried rewriting the if (key == CODED) section several different ways. The last 2 (failed) iterations remains in the CLASS for viewers’ reference.

At the very least, is this direction correct?
Comments most welcome!!

//////////////////////////////

// 2D Grid Array of Button objects
Button [][] myButtons;

// Number of columns and rows in the grid
int num = 10;
int cols = num, rows = cols;


color background = color (random(255), random(255), random(255));

void setup() {
  size(500, 500);

  int x = (width/num)/2, y = x;

  myButtons = new Button[cols][rows];
  for (int i = 0; i < cols; i++) {
    for (int j = 0; j < rows; j++) {
      // Initialize each object
      myButtons[i][j] = new Button (x+ i*(width/cols), y+ j*(height/rows), 
        color (random(255), random(255), random(255)), // random colors
        color (random(255), random(255), random(255)), // new random colors when mouseOver
        (width/num));
    }
  }
}

void draw() {

  background(background);


  for (int i = 0; i < cols; i++) {
    for (int j = 0; j < rows; j++) {
      myButtons[i][j].mouseOver();
      myButtons[i][j].display();
      myButtons[i][j].move(); //move() commented out in class
    }
  }
}

///////////////////////////////////

class Button {
  float x, y;
  color colRect;
  color colRect2;

  float sz;
  boolean off = true; // button starts in OFF position

  Button ( 
    float tempX, float tempY, 
    color tempColor, color tempColor2, float tempSz) {

    x = tempX;
    y = tempY;

    colRect = tempColor;
    colRect2 = tempColor2;

    sz = tempSz;
  }

  void display() {
    if (off) {
      fill (colRect);
      noStroke();
    } else {
      fill (colRect2);
      noStroke();
    }

    rectMode(CENTER);
    rect(x, y, sz, sz);
  }

  void mouseOver() {

    if (mouseX > x - sz/2 && 
      mouseX < x + sz/2 &&
      mouseY > y - sz/2 &&
      mouseY < y + sz/2) {

      off = false;
    } else {
      off = true;
    }
  }
}
/*void move() {        //trying to create a move function using cursor keys and failing 
                       void keyPressed() {
 if (key == CODED) {
 if (keyCode == UP) {
 y = y+1;
 } else if (keyCode == DOWN) {
 y = y-1;
 } else if (keyCode == LEFT) {
 x = x-1;
 } else (keyCode == RIGHT) {
 x = x+1;
 }
 }
 }
 }
 }
 void keyPressed() {
 if (keyCode== RIGHT)
 x++;
 if (keyCode== LEFT)
 x--;
 if (keyCode== UP)
 y++;
 if (keyCode== DOWN)
 y--;
 if (x < 0) x = 0;
 if (x > width) x = width;
 if (y < 0) y = 0;
 if (y > height) y = height;
 }*/

Remember to hit ctrl-t regularly to get better indents

A keyPressed inside the class won’t be called by processing. You can find out those things when you just place println (“1”); at the start of the method.

I moved the keyPressed() to the main program, but now am getting error y variable does not exist.
Also, I’m not sure what below quote means…

Button [][] myButtons;

// Number of columns and rows in the grid
int num = 10;
int cols = num, rows = cols;

color background = color (random(255), random(255), random(255));

void setup() {
  size(500, 500);

  int x = (width/num)/2, y = x;

  myButtons = new Button[cols][rows];
  for (int i = 0; i < cols; i++) {
    for (int j = 0; j < rows; j++) {
      // Initialize each object
      myButtons[i][j] = new Button (x+ i*(width/cols), y+ j*(height/rows), 
        color (random(255), random(255), random(255)), // random colors
        color (random(255), random(255), random(255)), // new random colors when mouseOver
        (width/num));
    }
  }
}

void draw() {

  background(background);


  for (int i = 0; i < cols; i++) {
    for (int j = 0; j < rows; j++) {
      myButtons[i][j].mouseOver();
      myButtons[i][j].display();
    }
  }
}
void keyPressed() {
  
      if (key == CODED) {
        if (keyCode== UP) {
          y = y+1;
        } else if (keyCode== DOWN) {
          y = y-1;
        } else if (keyCode== LEFT) {
          x = x-1;
        } else if (keyCode== RIGHT) {
          x = x+1;
        }
      }
    }

Sorry, you can leave keyPressed inside the class but you have to call it from a function with the same name outside the class

This what I’ve got now. The entire grid increments as a whole. The clue: [x+1][y], I can’t figure out how (where) to add the +1 / -1 to cell index so as to move individual cells.

I think(?) something sh’d be added to the void keyReleased() code block, but am not sure what.

// 2D Grid Array of Button objects
Button [][] myButtons;

// Number of columns and rows in the grid
int num = 10;
int cols = num, rows = cols;

color background = color (random(255), random(255), random(255));

void setup() {
  size(500, 500);

  int x = (width/num)/2, y = x;

  myButtons = new Button[cols][rows];
  for (int i = 0; i < cols; i++) {
    for (int j = 0; j < rows; j++) {
      // Initialize each object
      myButtons[i][j] = new Button (x+ i*(width/cols), y+ j*(height/rows), 
        color (random(255), random(255), random(255)), // random colors
        color (random(255), random(255), random(255)), // new random colors when mouseOver
        (width/num));
    }
  }
}

void draw() {

  background(background);


  for (int i = 0; i < cols; i++) {
    for (int j = 0; j < rows; j++) {
      myButtons[i][j].mouseOver();
      myButtons[i][j].display();
    }
  }
}
void keyReleased() {

  for (int i = 0; i < cols; i++) {
    for (int j = 0; j < rows; j++) {
      myButtons[i][j].keyPressed();
    }
  }
}

//////////////////////////////

class Button {
  float x, y;
  color colRect;
  color colRect2;

  float sz;
  boolean off = true; // button starts in OFF position

  Button ( 
    float tempX, float tempY, 
    color tempColor, color tempColor2, float tempSz) {

    x = tempX;
    y = tempY;

    colRect = tempColor;
    colRect2 = tempColor2;

    sz = tempSz;
  }

  void display() {
    if (off) {
      fill (colRect);
      noStroke();
    } else {
      fill (colRect2);
      noStroke();
    }

    rectMode(CENTER);
    rect(x, y, sz, sz);
  }

  void mouseOver() {

    if (mouseX > x - sz/2 && 
      mouseX < x + sz/2 &&
      mouseY > y - sz/2 &&
      mouseY < y + sz/2) {

      off = false;
    } else {
      off = true;
    }
  }

  void keyPressed() {

    if (key == CODED) {
      if (keyCode== UP) {
        y = y+1;
      } else if (keyCode== DOWN) {
        y = y-1;
      } else if (keyCode== LEFT) {
        x = x-1;
      } else if (keyCode== RIGHT) {
        x = x+1;
      }
    }
  }
}

in this version

int num = 10,cols = num, rows = cols;          // Number of columns and rows in the grid
Button [][] myButtons= new Button[cols][rows]; // 2D Grid Array of Button objects
color background = color (random(255), random(255), random(255));

void setup() {
  size(500, 500);
  int x = (width/num)/2, y = x;
  for (int i = 0; i < cols; i++) {
    for (int j = 0; j < rows; j++) {
      // Initialize each object
      myButtons[i][j] = new Button (x+ i*(width/cols), y+ j*(height/rows), 
        color (random(255), random(255), random(255)), // random colors
        color (random(255), random(255), random(255)), // new random colors when mouseOver
        (width/num));
    }
  }
}

void draw() {
  background(background);
  for (int i = 0; i < cols; i++)
    for (int j = 0; j < rows; j++)     
      myButtons[i][j].display();
}
void keyReleased() {

  for (int i = 0; i < cols; i++) {
    for (int j = 0; j < rows; j++) {
      myButtons[i][j].keyPressed();
    }
  }
}

//////////////////////////////

class Button {
  float x, y;
  color colRect;
  color colRect2;

  float sz;
  boolean off = true; // button starts in OFF position

  Button ( 
    float tempX, float tempY, 
    color tempColor, color tempColor2, float tempSz) {

    x = tempX;
    y = tempY;

    colRect = tempColor;
    colRect2 = tempColor2;

    sz = tempSz;
  }

  void display() {
    mouseOver();
    if (off)   fill (colRect);
    else       fill (colRect2);
    noStroke();
    rectMode(CENTER);
    rect(x, y, sz, sz);
  }

  void mouseOver() {
    if (mouseX > x - sz/2 && 
      mouseX < x + sz/2 &&
      mouseY > y - sz/2 &&
      mouseY < y + sz/2)       off = false;
    else                       off = true;
  }

  void keyPressed() {
    if ( ! off ) {
      if      (keyCode== UP)    y -= 1;
      else if (keyCode== DOWN)  y += 1;
      else if (keyCode== LEFT)  x -= 1;
      else if (keyCode== RIGHT) x += 1;
    }
  }
}

the mouse position selects a rectangle
and the keyboard operation does move only that on rectangle
( it was not clear if that is the operation concept you wanted to test )
it is not a very good concept as when the rect moves it will go outside the mouse position and stop moving…

possibly change to mouse click selects one rectangle ( might need to deselect all others )
and then key can move it around the canvas

2 Likes

Sorry for the misunderstanding.

This was an old post by me.

What I meant was that you could have one field that holds the player like in the game Snake. Now with cursor keys you could steer the player around. So you could store the player Pos as index of the grid like playerPosX and playerPosY and the cell class would have a field hasPlayer. Then you could move the player easily.

That would demonstrate the advantage of 2D grid over 1D array in that case. Because you just say +1, -1 to the 2 indexes, in a 1D list, that would be harder to do.

(The position of the grid cells remains the same, just the player wanders)

Sorry again, Chrisir

1 Like

Thank you very much @kll!! That gets me closer to the cursor interaction I’m looking for. I’ll play with this some more.
:grinning: :grinning:

No problem. Now I see what you’re saying… That makes sense.
I will try that in another sketch.
Many thanks!!
:grinning: :grinning:

1 Like

Make all cells same size and color

The Player is a circle on the cells

1 Like