Shapes 4x4 screen location

Hey there, everyone!
I’m pretty new to Processing and I’m having a hard time locating shapes on the screen.
TASK
Create 16 shapes, laying 4x4 on screen, filled with random colors and value of vertex of each next shapes must be random.

CODE

import java.util.Random;

void setup() {
  size(1600, 900);
  stroke(255, 0, 0);
}
void draw() {
  for(int k = 0; k < 4; k++) {
    translate(0, 110);
    for(int i = 0; i < 16; i+=4) {
          translate(95, 0);
          fill(random(255),random(255),random(255));
          beginShape();
           vertex(randInt(5, 10) * 1.2, randInt(5, 20) * 1.2);
           vertex(randInt(0, 10) * 1.2, randInt(60, 80) * 1.2);
           vertex(randInt(40, 70) * 1.2 , randInt(90, 110) * 1.2);
           vertex(randInt(50, 80) * 1.2, randInt(1, 20) * 1.2);
          endShape(CLOSE);
      } noLoop();
   }
}

int randInt(int min, int max) {
    Random rand = new Random();
    int randomNum = rand.nextInt((max - min) + 1) + min;
    return randomNum;
}

WHAT CODE DOES
It’s creating 16 shapes, filled with random values of vertex and locating it 140 pixels on y-axis and 95 on x-axis.

WHAT I NEED TO GET IN THE END(left side) AND WHAT I’M GETTING(right side)

QUESTION
Does somebody know, how to locate those shapes, as it’s required in task?

P.S.
Sorry for my English, haven’t been practiсing it for a long time :slight_smile:

Try pushMatrix before this and

popMatrix after endShape

noLoop is in a for loop better have it at the end of draw()

void draw() {
  for(int k = 0; k < 4; k++) {
    translate(0, 110);
    for(int i = 0; i < 16; i+=4) {
        pushMatrix();
          translate(95, 0);
          fill(random(255),random(255),random(255));
          beginShape();
           vertex(randInt(5, 10) * 1.2, randInt(5, 20) * 1.2);
           vertex(randInt(0, 10) * 1.2, randInt(60, 80) * 1.2);
           vertex(randInt(40, 70) * 1.2 , randInt(90, 110) * 1.2);
           vertex(randInt(50, 80) * 1.2, randInt(1, 20) * 1.2);
          endShape(CLOSE);
        popMatrix();
      } 
   }
   noLoop();
}

Still getting wrong location :frowning:
image

now they are on top of each other

try this. It uses i to calculate the x-position. 133 is the distance from the border


      translate(95*i +133, 0);
1 Like

it might look better with noStroke();

or stroke(0); before beginShape()

(the outline of the shapes)

1 Like

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:
image

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:
image

1 Like

Thank you so much, guys!
Problem seems to be solved for me

1 Like