Could someone explain this code to me

Hi everyone,
I wonder if someone can explaine to me how this code work :

int locX, locY;
int offsetX, offsetY;
 
final int unit = 32;
byte[][] terrain = new byte[10][10];

void setup() {
  size(321, 321);
 
  for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
      terrain[i][j] = byte(ceil(noise(i*0.05,j*0.05)*6));
    }
  }
}

void draw() {
  for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
      offsetX = i;
      offsetY = j;
 
      // Out of bounds
      if (offsetX < 0 || offsetX > 9 || offsetY < 0 || offsetY > 9) fill(0xff808080); //grey
 
      // Draw based on terrain
      else {
        if (terrain[offsetX][offsetY]>5){
          fill(0xff005000); //dark green
        }
        else if (terrain[offsetX][offsetY]>4){
          fill(0xff008000); //light green
        }
        else if (terrain[offsetX][offsetY]>3){
          fill(0xffc0c000); //yellow
        }
        else {
          fill(0xff0000c0); //blue
        }
      }
      rect(i*unit, j*unit, unit, unit);
    }
  }
}

I understand (i think) that in the setup(), each “i” and “j” get a random number between “i” * 0.05 and “j” *0.05 and then multiply by 6.

And then in the draw(), it check if the values of terrain[offsetX][offsetY] is more than a number i choose and color the rectangles.

So i get that everything is based on : byte[][] terrain = new byte[10][10];
but i dont understand precisely how it’s work and how to controle the result.

Thanks for your times.

1 Like

first of all terrain is a 2D array

similar to a chess board you need to indexes to get one of its cell.

The code below shows the indexes x,y

see https://www.processing.org/tutorials/2darray/


int locX, locY;
int offsetX, offsetY;

final int unit = 32;
String[][] terrain = new String[10][10];

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

  for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
      terrain[i][j] = i+"," +j;
    }
  }
}

void draw() {
  for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
      offsetX = i;
      offsetY = j;


      fill(0xff808080); //grey


      rect(i*unit, j*unit, unit, unit);
      fill(0); 
      text(    terrain[i][j], 
        i*unit+4, j*unit + 17);
    }
  }
}
1 Like

ok so each rect has a specific x and y indexes.
So this part of the code :

for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
      terrain[i][j] = byte(ceil(noise(i*0.05,j*0.05)*10));
    }
  }

create a random number based of the index of each rect.
Am i right ?

Yes.

see https://www.processing.org/reference/noise_.html

ceil then rounds this float value up (we get an int) and
byte() converts it to byte, which is not really necessary

see


int locX, locY;
int offsetX, offsetY;

final int unit = 32;
int[][] terrain = new int[10][10];

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

  for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
      terrain[i][j] = ceil(noise(i*0.05, j*0.05)*6);
    }
  }
}

void draw() {
  for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
      offsetX = i;
      offsetY = j;

      // Out of bounds
      if (offsetX < 0 || offsetX > 9 || offsetY < 0 || offsetY > 9) fill(0xff808080); //grey

      // Draw based on terrain
      else {
        if (terrain[offsetX][offsetY]>5) {
          fill(0xff005000); //dark green
        } else if (terrain[offsetX][offsetY]>4) {
          fill(0xff008000); //light green
        } else if (terrain[offsetX][offsetY]>3) {
          fill(0xffc0c000); //yellow
        } else {
          fill(0xff0000c0); //blue
        }
      }
      rect(i*unit, j*unit, unit, unit);
    }
  }
}

ok so each rect get one random number based on his indexes. (ex: the top left rect get the number 4)
Then this number (4 in my example) is checked by the conditions and get a color.

Am i still right ?

why is it not necessary ?

Yes you are right with the colors.

It might help to read the reference of noise()

You could also work with int instead of byte. I changed my post above to demonstrate this

the sketch has the purpose to make a landscape / terrain with water, desert, grass and forest or whatever I guess

yes, so if i get it right. To controle the result of my code i need to calculate and know the range of the number given by the randomization

You could store the result (the terrain) on the hard drive and load it from there.

Also noiseSeed seems to control noise to get the same result every time.

see https://www.processing.org/reference/noiseSeed_.html

here is a text file that my version just produced

3333332222
3333333222
4433333333
4443333333
4444433333
4444433333
4444444333
5554444433
5555444444
5555544444

or

6666555554
6665555554
5555555554
5555555444
4444444444
4444444444
4444444444
3333333444
3333333333
3333333333

or

6666555554
6666555554
5555555554
5555555554
5555555555
4445555555
4444555555
4444444555
3334444445
3333344445

Chrisir

and if i take the bottom right rect as an example, his index is 9,9. How the randomization work ?
if the rect indexes are 1,9 does it take a random number between 1 * 0.05 and 9 * 0.05 or does it work differently ? And so for the bottom right rect does it take a random number between 9 * 0.05 and 9 * 0.05 ?

it’s the randomization part of the code that i don’t understand completly

it would help to read the reference about noise.

I posted the link above

see noise() / Reference / Processing.org

It’s not a random.

Think of it more as a landscape of random values.

with this formula : noise(i*0.05, j*0.05)

we retrieve the value at point i*0.05, j*0.05 (x,y) in this landscape.
The result is a constant between 0 and 1. We multiply it by 6 so it’s between 0 and 6 and then we use ceil() to round it up. So it’s an integer between 1 and 6.

But 1,2,3 are all blue:

       else {
          fill(0xff0000c0); //blue
        }

No, it’s the random value at 9 * 0.05 and 9 * 0.05 in the 2D random landscape.


the resulting values are 1,2,3,4,5,6 or so.


here is a new code.

It saves the terrain (file gets overwritten every time !!!) and you can hit Space Bar to renew


int locX, locY;
int offsetX, offsetY;

final int unit = 32;
int[][] terrain = new int[10][10];

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

  randomizeNoise();
}

void draw() {
  for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
      offsetX = i;
      offsetY = j;

      // Draw based on terrain
      if (terrain[offsetX][offsetY]>5) {
        fill(0xff005000); //dark green
      } else if (terrain[offsetX][offsetY]>4) {
        fill(0xff008000); //light green
      } else if (terrain[offsetX][offsetY]>3) {
        fill(0xffc0c000); //yellow
      } else {
        fill(0xff0000c0); //blue
      }

      rect(i*unit, j*unit, 
        unit, unit);

      fill(0); 
      text(terrain[i][j], 
        i*unit+4, j*unit + 17);
    }
  }

  String[] s1=new String[10]; 
  for (int i = 0; i < 10; i++) {
    s1[i] = ""; 
    for (int j = 0; j < 10; j++) {
      s1[i] += terrain[i][j];
    }
  }

  saveStrings( "TT.txt", s1);
  //noLoop();
}

// ==============================================================

void keyPressed() {
  // SPACE BAR or any key 
  randomizeNoise();
}

void randomizeNoise() {
  noiseSeed( int(random(11111) ) ); 
  for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
      terrain[i][j] = ceil(noise(i*0.05, j*0.05)*6);
    }
  }
}
//
1 Like

Thanks, now i have a better understanding of the code. i readed the noise reference but I did not understand it well. Until now thank to you.

1 Like

I am not an expert on noise() but it seems like a more slow change of values than with random.

when you replace the noise line with
terrain[i][j] = ceil(random(0, 6));

it works technically, BUT you receive a very wacky and turbulent landscape:


1665355624
2134365332
3232264115
4622222256
6663363453
4422416452
6416532363
3642513355
4466315435
5444366442

(no long smooth connected patches of one kind of terrain!)

when you want to use the landscape maybe you can save with one program (my code above) and load with another one.

Or you produce 10 different maps in setup and find a way to identify the best. But how to measure this?

  • You could make sure that 3,4,5,6 are all present in the map and are all over 3 occurrences for example.

that’s a good idea, now than i have a better understanding of this code i will dive into it and find a good way to use it.

Thank you.

2 Likes

just for the sake of completeness:

this version loads a txt file.

You have to copy it from the folder of the previous sketch.

(the letters in the text file are upside down (or grid is rotated by 180°), but the terrains are the same in both Sketches. You can edit the text file in a text editor when you know what number signifies which type or terrain, but it’s rotated)

Chrisir

// THIS VERSION LOADS 

int locX, locY;
int offsetX, offsetY;

final int unit = 32;
int[][] terrain = new int[10][10];

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

  String[] stringsFromFile = loadStrings("TT.txt");

  int x=0; 
  for (String s1 : stringsFromFile) {
    for (int i=0; i < s1.length(); i++) {
      terrain[x][i]= (int) (s1.charAt(i)-48);
    }
    x++;
  }
  //
}// func 

void draw() {
  for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
      offsetX = i;
      offsetY = j;

      // Draw based on terrain
      if (terrain[offsetX][offsetY]>5) {
        fill(0xff005000); //dark green
      } else if (terrain[offsetX][offsetY]>4) {
        fill(0xff008000); //light green
      } else if (terrain[offsetX][offsetY]>3) {
        fill(0xffc0c000); //yellow
      } else {
        fill(0xff0000c0); //blue
      }

      rect(i*unit, j*unit, 
        unit, unit);

      fill(0); 
      text(terrain[i][j], 
        i*unit+4, j*unit + 17);
    }
  }

  String[] s1=new String[10]; 
  for (int i = 0; i < 10; i++) {
    s1[i] = ""; 
    for (int j = 0; j < 10; j++) {
      s1[i] += terrain[i][j];
    }
  }
}
//
2 Likes