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.