日々のこと

まいにちの暮らしをつれづれ書きます

p5.jsで雪を降らせてみた

会社のアドベントカレンダーに書こうと思っていたのですが、時間的に、あまり凝ったものができなそうだったので、ここにひっそりと貼ろうと思います。

前、仕事で、p5.jsをさわってみたことがありました。
Processingという、電子アートとビジュアルデザインのためのプログラミング言語があり、アートっぽい視覚的表現をすることができます。
そのProcessingJavaScriptに移植したのがp5.jsです。
p5.jsは、JavaScriptなので、ブラウザで動かすことができます。

もうすぐクリスマスなので、クリスマスっぽいことをしたいと思っていました。

雪の結晶を降らせてみました。
大きさは、乱数で変えています。

p5.jsをブラウザで編集して動かすことができる、p5.js Web Editorで作りました。

editor.p5js.org

コードです。

let snowflakes = [];

function preload() {
  backimage = loadImage('assets/merry-go-round.jpg');
  snowA = loadImage('assets/snowC.png');
}

function setup() {
  createCanvas(426, 525);
  noStroke();
  fill(255);
  frameRate(30);
}

function draw() {
  image(backimage, 0, 0);
  let time = frameCount / 60; // 更新時間(frameCountを60で割った数字)

  // フレームごとに、乱数分の雪片を作成してsnowflakes配列に入れる
  for (let i = 0; i < random(3); i++) {
    snowflakes.push(new Snowflake());
  }

  for (let flake of snowflakes) {
    flake.update(time); // 雪片の位置を更新する
    flake.display();    // 雪片を描く
  }
}

class Snowflake {
  constructor() {
    // 座標の初期化
    this.posX = 0; // 0で初期化
    this.posY = random(-50, 0); // -50から0の間の数値で初期化
    this.initialAngle = random(0, 2 * PI); // 初期の角度
    this.size = random(3, 10);  // 大きさ(2-5の間の乱数)
    
    // 雪片の螺旋の半径
    // 半径の2乗を最大値に生成した乱数の平方根を設定
    // (雪片が一斉に広がるようにするため) 
    this.radius = sqrt(random(pow(width / 2, 2)));
  }

  update(time) {
    // x座標:円に沿って動く
    let w = 0.6; // 角度のスピード
    let angle = w * time + this.initialAngle;
    this.posX = width / 2 + (this.radius * sin(angle));

    // y座標:異なるサイズの雪片はわずかに異なるy速度で落下する
    this.posY += pow(this.size, 0.5);

    // 画面の最後にきた雪片を削除
    if (this.posY > height) {
      let index = snowflakes.indexOf(this);
      snowflakes.splice(index, 1);
    }
  }

  display() {
    image(snowA, this.posX, this.posY, this.size, this.size);
  }
}

p5.jsのサンプルページに、コードと描画結果が乗っています。

p5js.org

雪が降ってくるところは、Snowflakesのサンプルを基にして書きました。雪が降るところはほぼサンプルそのままです(汗)

あしたはクリスマスイブ。よいクリスマスを!🎄