Pyramid Rect Pattern

Hello! I’m making a pyramid pattern with rects using for loops.

It’s a bit hard to explain, but basically, I would like to divide a square canvas into four triangular quadrants and fill each side with pyramids made from rects! The left and right sides have 20 bricks on the lowest row and work their way up to one, and the same goes for the top and bottom, but they only start with 19 bricks.

I was given this reference code for the right side. I do not need the solution for the entire code above, if someone could only explain what is happening in this code (as it’s quite confusing for me and I have no idea what’s going on)! I mainly need help with the operations going on in the rect(). (I also know all the method things and stuff like that, I’m just confused about the actual part where the pyramid is being drawn.)

I am pretty new to Processing and coding as a whole, so please excuse me being quite plainly dumb!

Thank you in advance!

float rbw, rbh, rbx, rby;

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

 drawRightSideBricks();
}

  void drawRightSideBricks(){
 rbw = (width/2)/20;
 rbh = height/20;
 rbx = width - rbw;
 rby = 0;
 
 for (int j=0; j<20; j++){
   for (int i=0; i<20-j; i++){
     fill(200, 50, 50);
     stroke(255);
     rect(rbx-j*rbw, rby+i*rbh, rbw, rbh);
   }
   rby += rbh/2;
 }
}
1 Like

Hi @chemicalite

I commented the code and added 2 new variables in hope that you would better understand the code:

float rbw, rbh, rbx, rby;

int horNb, vertNb;

void setup() {
  size(400, 400); 
  
  horNb = 5;
  vertNb = 5;

  drawRightSideBricks();
}

void drawRightSideBricks() {
  rbw = (width / 2) / horNb; // Get width of your bricks
  rbh = height / vertNb;     // Get height of your bricks
  rbx = width - rbw;         // The x position of the first brick you place. It is the top right brick and it represents the top left corner of that brick since the rect function uses this the top left corner of the rectange to draw a rectangle
  rby = 0;                   // The y position of the first brick you place.

  for (int j = 0; j < horNb; j++) { // For every column of bricks (you know there are horNb number) starting with the one on the right
    for (int i = 0; i < vertNb - j; i++) { // For every row of bricks. The way it works is that the first column (j = 0) has vertNb of bricks, the second column (j = 1) has vertNb - 1 brick, the third (j = 2) vertNb - 2 and so on. So for a given column, you have vertNb - j number of bricks to place
      fill(200, 50, 50);
      stroke(255);
      
      // (rbx - j * rbw) is the x position of the top left corner of the brick you want to place.
      // for every column, the x position is the x position of the first birck minus the width of the bricks multiply by the column we are at.
      // For the first column, j = 0 so the x position is the original position rbx
      // For the second column, j = 1 so the x postion is the original position minus one width
      // For the third, it is the original position minus 2 width and so on
      
      // (rby + i * rbh) is the y position of the top left corner of the brick you want to place.
      // THe idea is simlar to the x position. Depending on the row you add to the original y position the heigth of the bricks
      rect(rbx - j * rbw, rby + i * rbh, rbw, rbh);
    }
    
    // This row is used to move the start y position of the bricks by half the height of the brick after every column
    // The what's make it looks like a stair
    // If you comment that line, all your brick will start a the top of the screen
    rby += rbh/2; 
  }
}

1 Like

Thank you so much, that was extremely helpful!

Really, I can’t thank you enough! I finally understand it now!!

The extra variables definitely helped, too- I’ll probably end up using extra variables when I code the rest of my little project!

So, if I were to change the pyramid to starting at the top and descending towards the bottom, would I flip the variable values?

1 Like

For the most part yes. With few exta adjustment I think.

Try something and if you can’t manage to get it right, come back here with the code that you have and we’ll help you.

Thank you for the help!

Here’s my little troubleshooting thing going on- I tried flipping the x and y formulas, which resulted in the bricks being in the correct spot but the wrong orientation. I then tried flipping the width and height values along with that, which made this weird spacing between the rows. I then decided to change rby to rbx in the last line of the code that makes the bricks arranged stair-like, though that brought the spacing to the columns!

I also have no idea what variables to change to get it to descend from the top :confused:

I feel like I’m getting somewhere, but I don’t know what the next step would be! Here’s what I have now (just the flipped x and y formulas in the rect(), the other edits seemed wrong):

  void drawBottomSideBricks(){
 rbw = (width/2)/20;
 rbh = height/20;
 rbx = width - rbw;
 rby = 0;
 
 for (int j=0; j<20; j++){
   for (int i=0; i<20-j; i++){
     fill(200, 50, 50);
     stroke(255);
     rect(rby+i*rbh, rbx-j*rbw, rbw, rbh);
   }
   rby += rbh/2;
 }
}
1 Like

Ok let’s take it step by step.

First you really need to understand how the rect function works because we are using the top left cornet of each brick as a reference point to draw the brick. Every position and dimension will be based on the particular corner so this is the position of all those top left corners that we need to find.

Let’s start simple and create a function that draw a brick at a given position:

void setup() {
  size(400, 400);
}


void draw() {
  background(20);
  
  drawBrick(10, 20, 200, 50);  // draw a brick with the top left corner at the position (10, 20) with a width of 200 and a height of 50 
  drawBrick(200, 200, 50, 10); // draw a brick with the top left corner at the position (200, 200) - the center - with a width of 50 and a height of 10 
}


void drawBrick(float x, float y, float w, float h) {
  // Set the drawing parameters
  fill(200, 20, 20);
  stroke(230);
  strokeWeight(1);
  
  // Draw the brick as the rectangle
  // By default the rect() function draw a rectangle with the top left corner beeing at the (x, y) position with a width of w and a height of h
  rect(x, y, w, h);
}

Be sure to play with the code to really understand how the rectangle are positionned and what are the parameters needed.
Just to be sure we are on the same page, the x goes from left to right and y from top to bottom.

Now let’s go a bit further.
The first thing you need to figure out is what are the variables/parameters that will influence the way you program is working. The first thing that might come to you mind is the width and height of you bricks. If you change those values, the result will looks different.
But actually what really is important is the number of bricks that you want your first row to have. Based on that value, you will be able to get the width (because all the bricks should fit in the screen) and the height (because all the bricks should fit in half the height and there should be as many layers as there are bricks in the first row to have that pyramid shape.
Now we get that we can start defining what variable we should use and how to set them up:

int nbOfBricks;
float brickWidth;
float brickHeight;

void setup() {
  size(400, 400);
  
  nbOfBricks = 10;                            // The number of bricks we want in the first row  --->  Try changing the numbers to see how it changes the size of the brick
  brickWidth = width / nbOfBricks;            // All the bricks should fit in the width of the canvas
  brickHeight = (height / 2.0) / nbOfBricks;  // All the bricks should fit in half the height of the canvas and the is as many layers as ther are brick in the first row
}


void draw() {
  background(20);
  
  drawBrick(0, 0, brickWidth, brickHeight);   // Draw a brick at position (0, 0) with the calculated width and height
}


void drawBrick(float x, float y, float w, float h) {
  fill(200, 20, 20);
  stroke(230);
  strokeWeight(1);
  rect(x, y, w, h);
}

And because all our bricks will have the same size, we can simplify our drawBrick function like so:

int nbOfBricks;
float brickWidth;
float brickHeight;

void setup() {
  size(400, 400);
  
  nbOfBricks = 10;                            // The number of bricks we want in the first row  --->  Try changing the numbers to see how it changes the size of the brick
  brickWidth = width / nbOfBricks;            // All the bricks should fit in the width of the canvas
  brickHeight = (height / 2.0) / nbOfBricks;  // All the bricks should fit in half the height of the canvas and the is as many layers as ther are brick in the first row
}


void draw() {
  background(20);
  
  drawBrick(0, 0);   // Draw a brick at position (0, 0) with the calculated width and height
}


void drawBrick(float x, float y) {
  fill(200, 20, 20);
  stroke(230);
  strokeWeight(1);
  rect(x, y, brickWidth, brickHeight);
}

Now let’s say you want to do the bottom section.

The first step would be to place the bottom layer. For that, you know that you will need how many number of bricks you decided to have and that they will need to be drawn at the bottom and next to one another.

Let’s say we start by placing the brick on the bottom left of the screen.

You might want to write drawBrick(0, height) but remember the (x, y) position that you are giving is the position of the top left corner of the brick. And if the brick is at the bottom, the top left corner is not completely down but a bit higher, one height away from the bottom. So in this case you need to use drawBrick(0, height - brickHeight).

Ok so now the first brick is placed.

Now the next one should be on the right. But how far on the right? Well, one brick width away. So the second brick will be drawn with drawBrick(0 + brickWidth, height - brickHeight). The y position stay the same.

The one even after is 2 bricks away from the first one so we need to add 2 brickWidth: drawBrick(0 + 2 * brickWidth, height - brickHeight).

Of course you could do that manually but the best way would be to let the computer do all the hard work. They are there for that afterall =)

We know that we want to place N number of bricks, one next to each other. And doing by hand the first 2 bricks, we can see that a pattern start to emerge. The y position is always the same : height - brickHeight but the x position move depending on the brick number i 0 + i * brickWidth

Let’s use a for loop to do that:

int nbOfBricks;
float brickWidth;
float brickHeight;

void setup() {
  size(400, 400);
  
  nbOfBricks = 10;                            // The number of bricks we want in the first row  --->  Try changing the numbers to see how it changes the size of the brick
  brickWidth = width / nbOfBricks;            // All the bricks should fit in the width of the canvas
  brickHeight = (height / 2.0) / nbOfBricks;  // All the bricks should fit in half the height of the canvas and the is as many layers as ther are brick in the first row
}


void draw() {
  background(20);
  
  for (int i = 0; i < nbOfBricks; i++) {
    drawBrick(0 + i * brickWidth, height - brickHeight);
  }
}


void drawBrick(float x, float y) {
  fill(200, 20, 20);
  stroke(230);
  strokeWeight(1);
  rect(x, y, brickWidth, brickHeight);
}

Let’s now build our second layer.

The same way we did the first layer, let’s figure out the position of the most left brick.

For the y position, instead of beeing one brick height away from the bottom, we are two brick heights away since we are on the second layer so y = height - 2 * brickHeight.

For the x position, we don’t want to be on the complete left but rather in the middle of the brick just beneath. So because of that we need to move the brick half its width on the right. The x position is then : birckWidth / 2.

For the second brick, the idea is the same as for the first layer. The y position will be the same but the x position will need to be shifted on the right by the width of a brick. So the position of the second brick is (birckWidth / 2 + birckWidth, height - 2 * brickHeight). Keep in mind that the first brick x position was not 0 so we need to move away from its real x position and not 0.

With this idea, the third one will be at position (birckWidth / 2 + 2 * birckWidth, height - 2 * brickHeight).

Again we can see a pattern. The only difference with the first one is that now we want 1 brick less on this row and that the first brick is not at x = 0 but x = brickWidth / 2.

If we right another loop to create this row we would have:

int nbOfBricks;
float brickWidth;
float brickHeight;

void setup() {
  size(400, 400);
  
  nbOfBricks = 10;                            // The number of bricks we want in the first row  --->  Try changing the numbers to see how it changes the size of the brick
  brickWidth = width / nbOfBricks;            // All the bricks should fit in the width of the canvas
  brickHeight = (height / 2.0) / nbOfBricks;  // All the bricks should fit in half the height of the canvas and the is as many layers as ther are brick in the first row
}


void draw() {
  background(20);
  
  // First layer of bricks
  for (int i = 0; i < nbOfBricks; i++) {
    drawBrick(0 + i * brickWidth, height - brickHeight);
  }
  
  // Second layer of bricks
  for (int i = 0; i < nbOfBricks - 1; i++) {  // Keep in mind there is 1 brick less to draw on this layer
    drawBrick((brickWidth / 2.0) + i * brickWidth, height - 2 * brickHeight); // The first brick of the layer is not at x = 0 but x = (brickWidth / 2.0). The height also need to be changed
  }
}


void drawBrick(float x, float y) {
  fill(200, 20, 20);
  stroke(230);
  strokeWeight(1);
  rect(x, y, brickWidth, brickHeight);
}

Let’s add the third layer quickly. The logic is the same exept that this time y would be height - 3 * brickHeight, the x position 2 * (brickWidth / 2.0) and we have one less brick to draw compare to layer 2 so 2 less than the first layer.

If we add it to the code we would have:

int nbOfBricks;
float brickWidth;
float brickHeight;

void setup() {
  size(400, 400);
  
  nbOfBricks = 10;                            // The number of bricks we want in the first row  --->  Try changing the numbers to see how it changes the size of the brick
  brickWidth = width / nbOfBricks;            // All the bricks should fit in the width of the canvas
  brickHeight = (height / 2.0) / nbOfBricks;  // All the bricks should fit in half the height of the canvas and the is as many layers as ther are brick in the first row
}


void draw() {
  background(20);
  
  // First layer of bricks
  for (int i = 0; i < nbOfBricks; i++) {
    drawBrick(0 + i * brickWidth, height - brickHeight);
  }
  
  // Second layer of bricks
  for (int i = 0; i < nbOfBricks - 1; i++) {  // Keep in mind there is 1 brick less to draw on this layer
    drawBrick((brickWidth / 2.0) + i * brickWidth, height - 2 * brickHeight); // The first brick of the layer is not at x = 0 but x = (brickWidth / 2.0). The height also need to be changed
  }
  
  // Third layer of bricks
  for (int i = 0; i < nbOfBricks - 2; i++) { // 2 less bricks to draw compare to first layer
    drawBrick(2 * (brickWidth / 2.0) + i * brickWidth, height - 3 * brickHeight); // Move up the layer and start the layer a bit more in the right
  }
}


void drawBrick(float x, float y) {
  fill(200, 20, 20);
  stroke(230);
  strokeWeight(1);
  rect(x, y, brickWidth, brickHeight);
}

You could go and do it all by hand but first you would need to change it every time you want to change the number of bricks and 2nd our computer can still work a bit harder!

At this point you should see a new pattern appearing. For each layer, we move up by 1 brick height, we start the layer a bit more on the right and we draw one less brick than the previous layer.

It’s time for another for loop outside the first loop we created. The first one was to build one layer brick by brick, and the second outside one will be to change layer and offset the first tile the correct way.

I will leave the creation of that outer loop as an exercise and if you really can’t find how it’s done I’ll give you my version.

3 Likes

That was beyond helpful, I don’t even know what to say! Thank you so much for typing all of that out for me- it was definitely good for me to run through the actual function of a rect()!

With your help, I’ve finally figured out the code! Here’s the solution for anyone who would like a reference to it:

float rbw, rbh, rbx, rby;
float lbw, lbh, lbx, lby;
float tbw, tbh, tbx, tby;
float bbw, bbh, bbx, bby;

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


 drawBottomSideBricks();
 drawTopSideBricks();
 drawLeftSideBricks();
 drawRightSideBricks();
}

void drawLeftSideBricks(){
  lbw = (width/2)/20;
  lbh = height/20;
  lbx = 0;
  lby = 0;
  
  for (int g=0; g<20; g++){
    for (int b=0; b<20-g; b++){
      fill(50, 200, 50);
      stroke(255);
      rect(lbx+g*lbw, lby+b*lbh, lbw, lbh);
    }
    lby += lbh/2;
  }
}
    
  void drawRightSideBricks(){
 rbw = (width/2)/20;
 rbh = height/20;
 rbx = width - rbw;
 rby = 0;
 
 for (int j=0; j<20; j++){
   for (int i=0; i<20-j; i++){
     fill(200, 50, 50);
     stroke(255);
     rect(rbx-j*rbw, rby+i*rbh, rbw, rbh);
   }
   rby += rbh/2;
 }
}

void drawTopSideBricks(){
 tbw = width/20;
 tbh = (height/2)/20;
 tbx = tbw/2;
 tby = 0;
 
 for (int w=0; w<20; w++){
   for (int c=0; c<19-w; c++){
     fill(200, 200, 50);
     stroke(255);
     rect(tbx+c*tbw, tby+w*tbh, tbw, tbh);
   }
   tbx += tbw/2;
 }
}

void drawBottomSideBricks(){
 bbw = (width/20);
 bbh = (height/20)/2;
 bbx = bbw/2;
 bby = height-bbh;
 
 for (int w=0; w<20; w++){
   for (int c=0; c<19-w; c++){
     fill(50, 50, 200);
     stroke(255);
     rect(bbx+c*bbw, bby-w*bbh, bbw, bbh);
   }
   bbx += bbw/2;
 }
}

Once again, thank you so, SO much!! :smile:

1 Like

Cool, happy to see the result!

Nice job :+1: