Hello Waller,
Before heading to your issue, I just would like to point out that you don’t need to import the Random library as processing already offer a random() function.
That being said, if you do use the java Random library, then you don’t want to call this line: Random rand = new Random();
every time you run your random function. It defies the purpose of the object. Instead, you want rand to be defined in the global scope so you can simply use nextInt()
when needed.
Now, to answer you issue. A good way to think about it is to realize that you 16 shapes are almost the same and that the easiest way to position them is by position the center. So what you want to do is think that the center correspond to coordinates (0, 0) and define the other points around:
Keeping as much as your code as possible, it could looks something like this:
import java.util.Random;
Random rand = new Random();
void setup() {
size(800, 800);
stroke(255, 0, 0);
createRandomShape();
}
int randInt(int min, int max) {
return rand.nextInt((max - min) + 1) + min;
}
void createRandomShape() {
fill(random(255), random(255), random(255));
beginShape();
vertex(randInt(-98, -80), randInt(-98, -80));
vertex(randInt(80, 98), randInt(-98, -80));
vertex(randInt(80, 98), randInt(80, 98));
vertex(randInt(-98, -80), randInt(80, 98));
endShape(CLOSE);
}
I changed the size of the window to be 800 by 800 so I can divide the space with 200 by 200 square.
I also created a function to encapsulate the creation of a shape.
Now, since you want 16 shapes, it makes sense to use a for loop
to create your shape. A simple way would be to do:
for (int i = 0; i < 16; i++) {
createRandomShape();
}
But for what we want to do it is not the most convenient. Since you want to place your shapes in a grid pattern, it makes sens to think of it as having 4 columns and 4 rows. And to translate this idea into code, we can use 2 for loops
instead of one:
for (int r = 0; r < 4; r++) { // Loop through the "rows"
for (int c = 0; c < 4; c++) { // Loop through the "columns"
createRandomShape();
}
}
Running this piece of code won’t do what you want since all the shapes are drawn around the coordinate (0, 0);
So let’s forget our shape for the moment and let’s try to draw simple ellipses where our shapes should be. We know that we have split the space into 16 grids of 200 by 200 pixels, 4 columns and 4 rows. What we need is an ellipse in the middle of each of those squares.
We can easily figure out that the x coordinates of the columns as as such:
column 0 : x = 100
column 1 : x = 300
column 2 : x = 500
column 3 : x = 700
If we name c our column number, we can see that x = i * 200 + 100
The same would be true for y. So using our previous for loop, it is now easy to draw the ellipses where we want them:
void setup() {
size(800, 800);
noStroke();
background(20);
fill(220);
for (int r = 0; r < 4; r++) { // Loop through the "rows"
for (int c = 0; c < 4; c++) { // Loop through the "columns"
float x = c * 200 + 100;
float y = r * 200 + 100;
ellipse(x, y, 50, 50);
}
}
}
All left to do now is connect the part of the puzzle:
- We know how to create a shape centered around (0, 0)
- We know where we want to place those shapes
All left to do is to translate each shape to the proper location. But be careful, the translate() function is cumulative
. If you do translate(4, 6)
, then draw a shape, this shape will be moved by 4 pixels on the x axis and 6 and the y axis. All good. But if later on you do translate(10, 20)
, then draw a shape, then this time the shape will be moved by 10 + 4 = 14 pixels on the x axis and 20 + 6 = 26 pixels on the y axis.
To prevent this, you can use the push() and pop() functions. Everything transformations and style that you apply in between those functions will be valid only between those functions.
I will let you do the final code by yourself as an exercise: