クモのようにコツコツと

フロントエンドエンジニア イイダリョウの技術ブログ。略称「クモコツ」

【p5.js】クリエイティブコーディングに挑戦(その1)

p5.jsの続きです。前回はp5.js習得のためになりそうなサイトや書籍をまとめました。今回はその中でドットインストールの作例「p5.jsクリエイティブコーディング」が素敵だったので挑戦してみます。それではいきましょう!

【目次】

※前回:p5.jsを習得するために参考になりそうなサイト、書籍、動画たち - クモのようにコツコツと

クリエイティブコーディングの作例

今回、取り組むのはドットインストールの講座「p5.jsでクリエイティブコーディングを体験しよう」。

※参考:p5.jsでクリエイティブコーディングを体験しよう

1本目で完成品をいじっている。

f:id:idr_zz:20190620223916j:plain

※参考:#01 完成版で遊んでみよう

おお!グリッド状に配置されたドットがカーソルを載せると波紋状に大きさが変わる!色もランダムに変わる。

p5.jsをやりたい動機はユーザーの操作にインタラクティブに反応するところなのでモチベーションがあがる。

描画領域の設定

2本目の動画部分。早速やってみよう!

※参考:#02 描画領域の設定をしよう

まず、HTMLファイルでp5.jsのライブラリを読み込む。CDNありんす!

<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.8.0/p5.min.js"></script>

私がいつも使っているCodePenならJSの歯車アイコンのところでリンクできる。

f:id:idr_zz:20190620223818j:plain

準備完了したので、p5.js部分を作成。

function setup() {
  // 描画領域のセットアップ
}
  • 関数setup()の中に描画領域の設定を書いていく。

書いた。

See the Pen p5.js #2 by イイダリョウ (@i_ryo) on CodePen.

背景が黒い200px四方のcanvas要素ができた!

function setup() {
  // 描画領域のセットアップ
  createCanvas(200,200);
  background(0);
  noStroke();
  fill(255);
}
  • createCanvas()で幅200px、高さ200pxのcanvasを作成
  • background()で背景色RGB全て0(黒)
  • noStroke()で線を無しに
  • fill()で面の色をRGB全て255(白)

色の値を一つだけにするとRGB三色が全て同じ値になるのは独特な書き方。線や面の 設定はしているけど、まだオブジェクトがないので何も描かれていない。

グリッド作成

次はグリッドの作成。3番目の動画に進む!

※参考:#03 グリッドを作ってみよう

作った。

See the Pen p5.js #3 by イイダリョウ (@i_ryo) on CodePen.

3列3行の9つの点が現れた!

function setup() {
  //(中略)
  
  const size = 5;
  
  //楕円設定
  ellipse(50,50,size,size);
  ellipse(100,50,size,size);
  ellipse(150,50,size,size);

  ellipse(50, 100,size,size);
  ellipse(100,100,size,size);
  ellipse(150,100,size,size);

  ellipse(50,150,size,size);
  ellipse(100,150,size,size);
  ellipse(150,150,size,size);

}
  • 変数sizeに楕円のサイズを入れる(5px)
  • 楕円設定ellipse(左からの位置, 上からの位置, 幅, 高さ)で幅と高さにはsizeを入れる

ellipseは楕円という意味。5pxの楕円が左から50px、上から50pxのところから始まって、列も行も50pxずつ離れて描画された!

ただ、動画でも語られているように、ほとんど同じ内容で値の数字だけ変わっているのはメンテナンス性が低いのでループ化したい。

for文のループにする

for文でループにする。4本目の動画!

※参考:#04 二重ループを使ってみよう

やってみた。

見た目は同じ。コードは違う

function setup() {
  //(中略)
  
  //楕円ループ
  for(let x = 50; x <= 150; x += 50) {
    ellipse(x, 50,size,size);
  }
  
  for(let x = 50; x <= 150; x += 50) {
    ellipse(x, 100,size,size);
  }

  for(let x = 50; x <= 150; x += 50) {
    ellipse(x, 150,size,size);
  }
}
  • 楕円設定のところをfor文でループ化。条件xの初期値は50。150になるまでxに50ずつ足す(=3回分)
  • for文の中身はellipse()だが第一引数(左からの位置)をx
  • 第二引数(上からの位置)を変えたfor文を3つ書く

先ほどより冗長ではなくなったけど、ほとんど同じfor文を3つ重ねているのをなんとかしたい。「二重ループ」にする。

See the Pen p5.js #4-2 by イイダリョウ (@i_ryo) on CodePen.

またまた見た目は同じ。コードは違う。

function setup() {
  // (中略)
  //楕円 二重ループ
  for (let y = 50; y <=150; y +=50) {
    for(let x = 50; x <= 150; x += 50) {
      ellipse(x, y,size,size);
  }
}
  
}
  • 先ほどのfor文の外をfor文で囲う。
  • 外のfor文の条件yの初期値は50。150になるまでyに50ずつ足す(=3回分)
  • 中のfor文のellipse()の第二引数(上からの位置)をyにする

これでyを3回分50を足すfor文の中でxを3回分50を足して楕円を描画するので3 × 3で合計9回ループする。見た目がずいぶんスマートになった!あまりネストを深くするとわかりにくくなりそうな気もするけど、二重ループにするだけでこれだけすっきりするなら今後も使っていきたい。

円の数を増やす

次は円の数を増やす。

※参考:#05 円の数を増やしてみよう

See the Pen p5.js #5 by イイダリョウ (@i_ryo) on CodePen.

すっごい増えた!ジンベエザメの体みたいw

function setup() {
  // 描画領域のセットアップ
  createCanvas(600,200);
 //(中略)
  
  const size = 5;
  const step = 20;
  
  //楕円 二重ループ
  for (let y = 0; y <=height; y +=step) {
    for(let x = 0; x <= width; x += step) {
      ellipse(x, y,size,size);
  }
}
  
}
  • createCanvas()の第一引数を600(canvasの幅が600px)
  • 変数stepを追加。値を20に
  • 二重ループの条件1:yxもスタートを0に
  • 二重ループの条件2:yheightいっぱいまで、xwidthいっぱいまで続ける
  • 二重ループの条件3:step(20)ずつ足していく

widthheightと書くだけで幅や高さいっぱいまでのサイズを取得できるのは楽でいいですね♪

これでcanvasのサイズが大きくなり、端から端まで20px感覚で楕円がループされる。ジンベエザメの完成!

円のサイズをランダムにする

次は均等なジンベエザメ模様をランダムな円にする!

※参考: #06 乱数を使ってみよう

See the Pen p5.js #6-1 by イイダリョウ (@i_ryo) on CodePen.

リロードをすると毎回大きさが変わる。ランダムな円になった!

function setup() {
  // (中略)
  
  const step = 20;
  
  //楕円 二重ループ
  for (let y = 0; y <=height; y +=step) {
    for(let x = 0; x <= width; x += step) {
      const size = random(0, 15);
      ellipse(x, y,size,size);
  }
}
}
  • for文の外の変数をstepのみに
  • for文の中に変数sizeを設定。random()関数で0〜15の間に
  • ループでellipse()を実行されるたびにsizeにランダムな値が入る

変数sizeの位置をfor文の外に置いたままだとrandom()はページ読み込み時の1回しか実行されない。書く位置によって挙動が変わるのは面白く、今後も意識していきたい。

なお、random()はp5.jsで用意されている関数。

※参考:reference | p5.js

以前、おみくじの記事で触れた組み込み関数Math.random()に似ている。(random()は引数の値で0〜15など範囲を設定できる)

※参考:【JS】Math.random()でつくるサイコロとおみくじ - クモのようにコツコツと

動画では後半でランダム値にもっとメリハリをつける方法を解説していた。

See the Pen p5.js #6-2 by イイダリョウ (@i_ryo) on CodePen.

うむ、確かに前よりも大小差は強くなった。

function setup() {
  // (中略)

  const step = 20;
  
  //楕円 二重ループ
  for (let y = 0; y <=height; y +=step) {
    for(let x = 0; x <= width; x += step) {
      //const size = random(0, 15);
      let size;
      if(random() < 0.95) {
        size = random(0, 10);
      } else {
        size = step;
      }

      ellipse(x, y,size,size);
  }
}
  
}
  • for文の中に書いた変数sizeをいったんコメントアウト
  • 変数sizeの設定のみで値は書かない。
  • if文を設定。条件はrandom()が0.95以上であれば
  • random()の範囲を0〜10に
  • それ以外はstep(20)に

先ほどは0〜15まで満遍なくだったが、今回は0〜10とさっきより狭い範囲のランダムの中で0.95を超えた場合だけ極端に大きい20になる。差がより明確になっている。

20サイズの円が主役、他は脇役という感じのメリハリがついた。これもリロードのたびにランダムに位置が変わる。

最後に(次回は色と動き)

f:id:idr_zz:20190620234557j:plain

今回はキャンバスの設定、円の配置、円サイズのランダム化に取り組んだ。次回は後半戦、円の色をランダムに設定したり、カーソルに合わせて円のサイズが変わるインタラクティブコンテンツにしていきたく思う。それではまた!!

※続き書きました!

www.i-ryo.com


※参考:p5.jsを習得するためにやった事まとめ qiita.com