2021プログラミング7:乱数とジェネラティブな表現

生成される予測できない数列の要素を乱数と呼びます。Processingではrandom()関数を使って乱数を擬似的に生成することができます。

ランダムな線の描画
random()関数は呼び出すたびに異なる数値を返します。パラメータで値の上限あるいは値の範囲を指定することができます。たとえばrandom(10)とすると、0以上、10未満の乱数が生成されます。生成される数値は浮動小数点になるため、変数は float型を使います。
それでは、乱数を使って線を描画してみましょう。線の配色も乱数で生成しています。

function setup(){
   createCanvas(400, 400);
   background(255);
}

function draw(){
  for(let i = 0; i < 100; i++){
    stroke(random(255), random(255), random(255));
    line(random(width), random(height), random(width), random(height));
  }
}

ランダムな円の描画
次に円を乱数を使って描画してみましょう。

let speed = 5;
let x = 200;
let y = 200;

function setup(){
   createCanvas(400, 400);
   background(255);
}

function draw(){
    x += random(-speed, speed);
    y += random(-speed, speed);
    noStroke();
    fill(random(255), random(255), random(255));
    ellipse(x, y, 100, 100);
}

これらのグラフィックは、コードが実行されるたびに、その実行結果が異なることに気がついたでしょうか。
コードに規則を与えることで、予測は可能だが確定的ではないグラフィックスなどを生成することができます。

ジェネラティブなグラフィック表現
ここからは、参考書籍「ジェネラティブ・アート Processingによる実践ガイド マット・ピアソン著」を参考にジェネラティブ(生成的)なグラフィック表現に挑戦してみましょう。

円の描画
まずは、これまでどうりの方法で円を描いてみましょう。

let radius = 200;
let centerx = 400;
let centery = 400;

function setup(){
  createCanvas(800,800);
  background(255);
  strokeWeight(2);
  smooth();
}

function draw(){
  stroke(200, 200, 200);
  noFill();
  ellipse(centerx, centery, radius*2, radius*2);
}

円を描画する別の方法
次に三角関数を用いて点で円を描いてみましょう。

let radius = 200;
let centerx = 400;
let centery = 400;
let x, y;
let lastx = -999;
let lasty = -999;
let ang;
let rad; 

function setup(){
  createCanvas(800,800);
  background(255);
  strokeWeight(2);
  smooth();
}

function draw(){
  stroke(0, 0, 0);
  for(ang = 0; ang <= 360; ang += 2){
    rad = radians(ang);
    x = centerx + (radius * cos(rad));
    y = centery + (radius * sin(rad));
    point(x,y);
  }
}

円かららせんを描画する
円のコードをもとにして、らせんを描いてみましょう。

let radius = 10;
let centerx = 400;
let centery = 400;
let x, y;
let lastx = -999;
let lasty = -999;
let ang;
let rad; 

function setup(){
  createCanvas(800,800);
  background(255);
  strokeWeight(2);
  smooth();
}

function draw(){
  stroke(0, 0, 0);
  for(ang = 0; ang <= 1440; ang += 2){
    radius += 0.5;
    rad = radians(ang);
    x = centerx + (radius * cos(rad));
    y = centery + (radius * sin(rad));
    point(x,y);
  }
}

らせんを線で描画する
らせんを点ではなく線で描きましょう。

let radius = 10;
let centerx = 400;
let centery = 400;
let x, y;
let lastx = -999;
let lasty = -999;
let ang;
let rad; 

function setup(){
  createCanvas(800,800);
  background(255);
  strokeWeight(0.5);
  smooth();
}

function draw(){
  stroke(0, 0, 0);
  for(ang = 0; ang <= 1440; ang += 2){ radius += 0.5; rad = radians(ang); x = centerx + (radius * cos(rad)); y = centery + (radius * sin(rad)); if(lastx > -999){
      line(x, y, lastx, lasty);
    }
    lastx = x;
    lasty = y;
    lasty = y;
  }
}

らせんの線にノイズを加える
線にノイズを加えることで手書きの描線のようなゆらぎが現れます。

let radius = 10;
let centerx = 400;
let centery = 400;
let x, y;
let lastx = -999;
let lasty = -999;
let ang;
let rad; 
let radiusNoise;
let thisRadius;

function setup(){
  createCanvas(800,800);
  background(255);
  strokeWeight(0.5);
  smooth();
}

function draw(){
  stroke(0, 0, 0);
  radiusNoise = random(10);
  for(ang = 0; ang <= 1440; ang += 5){ radiusNoise += 0.05; radius += 0.5; thisRadius = radius + (noise(radiusNoise) * 200)-100; rad = radians(ang); x = centerx + (thisRadius * cos(rad)); y = centery + (thisRadius * sin(rad)); if(lastx > -999){
      line(x, y, lastx, lasty);
    }
    lastx = x;
    lasty = y;
  }
}

らせんに乱数を加え複数重ねて描画する
らせんの描線に乱数を加えながら複数のらせんを重ねて描いてみましょう。

let radius;
let centerx = 400;
let centery = 400;
let x, y;
let lastx;
let lasty;
let ang;
let rad; 
let radiusNoise;
let thisRadius;
let startangle;
let endangle;
let anglestep;

function setup(){
  createCanvas(800,800);
  background(255);
  strokeWeight(0.5);
  smooth();
}

function draw(){
  for(let i = 0; i < 100; i++){
    lastx=-999;
    lasty=-999;
    radius = 10;
    stroke(random(255), random(255), random(255),50);
    startangle = int(random(360));
    endangle = 1440 + int(random(1440));
    anglestep = 5 + int(random(3));
    radiusNoise = random(10);
    for(ang = startangle; ang <= endangle; ang += anglestep){ radiusNoise += 0.05; radius += 0.5; thisRadius = radius + (noise(radiusNoise) * 200)-100; rad = radians(ang); x = centerx + (thisRadius * cos(rad)); y = centery + (thisRadius * sin(rad)); if(lastx > -999){
        line(x, y, lastx, lasty);
      }
      lastx = x;
      lasty = y;
    }
  }
}

 

ジェネラティブ・アート
ジェネラティブ・アートと呼ばれる、数学的な手順(アルゴリズム)によって生成される芸術作品のジャンルが存在します。ジェネラティブ・アートを植物を例に解説していきます。植物は、同じ種類であれば、同じ葉や花のかたちで構成されますが、まったく同じではありません。陽の光や、水、土など生育環境からの要因によって、葉や花の大きさや、角度などが違って成長します。それらは、タネの段階では、どのように育つのかは確定的でなく、植えてから植物が育ってはじめて、その姿形が確認できます。また、常に成長している過程にあるので、その姿形は変化を続けています。このような植物の生育にも似た特徴を持つのが、ジェネラティブ・アートになります。

こうした、生成的な特徴を持つグラフィック作品を制作していきましょう。

課題:
乱数を用いてジェネラティブ・アートの概念をもったグラフィック作品を5点作成する。

ヒント:
繰り返し構文(for文)を使って、一定時間生成をし続けるような作品。
マウスボタンのクリックごとに新たな形態を生成させる作品。
音楽の音量にあわせて形態を無限に変化させ続ける作品。
など

締切:2022年1月20日(木)の授業内で作品発表する
課題提出について
コードのシェア機能を使って作成した作品のコードをシェアするリンクをWordにコピーアンドペーストし、
作品のリンク集を作成してください。
授業名、学籍番号、氏名を明記し、各作品ごとにタイトルと200字程度のコメントを付して、書類を完成させ、
PDF形式に変換してCSのデジタルコンテンツ実習Ⅵ(プログラミング)「プログラミング全課題提出」掲示板に
提出してください。

提出締切:2022年1月27日(木)まで

コードのシェア
作成したコードをシェア(他者と共有)することができます。p5js Editorにログインし、Fileメニューから
Shareを選択すると、コードをシェアするためのウィンドウメニューが表示されます。メニューのEditの欄に
表示されている文字列をコピーしてWordなどにコピーすると、コーディングで作成した作品へのリンクができる
ようになります。