JavaScript自体あまりさわったことのないフロントエンド初心者ですが、p5.jsに挑戦してみました。
p5.jsとは
p5.js は、ProcessingをJavaScriptに移植したものらしいです。
examples を見てみると、いろいろできそうな雰囲気です。
例えば、こんな例があります1
何を作ってみるか...
12月なので雪を降らせてみようと思ったのですが、すでに Snowflakes というサンプルがありました。。。
それなら、この雪を積もらせてみようと思います!!!
追加したコード
Snowflakesのサンプルを元に、いくつか処理を追加していきます。
一番下に到達した雪を固定する
一番下に到達した雪を固定するため、変数と描画の処理を追加しました。
let piledSnowflakes = [];
:
function draw() {
:
// draw piledSnowflakes
for (let piledFlake of piledSnowflakes) {
piledFlake.display();
}
:
}
function snowflake() {
:
// delete snowflake if past end of screen
if (this.posY > height) {
// add piledSnowflake instead of deleting snowflake
piledSnowflakes.push(this);
let index = snowflakes.indexOf(this);
snowflakes.splice(index, 1);
}
:
}
積もるラインをだんだん上にする
スクリーンの一番下に積もり続けるのではなく、積もる位置が徐々に上になっていくようにしました。
let piledSpeed = 0.05;
let piledHeight = -300 * piledSpeed;
:
function draw() {
:
piledHeight += piledSpeed;
:
}
// snowflake class
function snowflake() {
:
// delete snowflake if past end of piled snow line
if (this.posY > height - piledHeight) {
// add piledSnowflake instead of deleting snowflake
piledSnowflakes.push(this);
let index = snowflakes.indexOf(this);
snowflakes.splice(index, 1);
}
:
}
四角形で積もるようにする
上記の積もらせ方では雪と雪の間に隙間ができてしまい、見た目が綺麗になりませんでした。
そこで、下から四角形が積もっていくようにしました。
function draw() {
:
// draw piled snow using rectangle
piledHeight += piledSpeed;
fill('white');
rect(0, height - piledHeight, width, piledHeight);
:
}
積もった雪に埋もれた雪片は削除する
雪片のオブジェクトが増えていくと処理が重くなっていくため、積もった雪に埋もれたものは削除する処理を入れました。
function draw() {
:
// draw piledSnowflakes
for (let piledFlake of piledSnowflakes) {
piledFlake.deleteBuriedSnowflakes();
piledFlake.display();
}
}
:
function snowflake() {
:
// delete piledSnowflakes under piled snow line
this.deleteBuriedSnowflakes = function() {
if (this.posY > height - piledHeight + 5) {
let index = piledSnowflakes.indexOf(this);
piledSnowflakes.splice(index, 1);
}
};
}
結果
こんな感じになりました。
テーマがよくないのか、実装方針がよくないのか、、、
ちょっとしっくりきませんが、ひとまずこれでよしとします。
最終的なコード
今回の最終的なコードは以下の通りです。
p5.js Web Editor に貼り付けて動かすことができます。
let snowflakes = []; // array to hold snowflake objects
let piledSnowflakes = [];
let piledSpeed = 0.05;
let piledHeight = -300 * piledSpeed;
function setup() {
createCanvas(400, 600);
fill(240);
noStroke();
}
function draw() {
background('brown');
let t = frameCount / 60; // update time
// create a random number of snowflakes each frame
for (var i = 0; i < random(5); i++) {
snowflakes.push(new snowflake()); // append snowflake object
}
// loop through snowflakes with a for..of loop
for (let flake of snowflakes) {
flake.update(t); // update snowflake position
flake.display(); // draw snowflake
}
// draw piled snow using rectangle
piledHeight += piledSpeed;
fill('white');
rect(0, height - piledHeight, width, piledHeight);
// draw piledSnowflakes
for (let piledFlake of piledSnowflakes) {
piledFlake.deleteBuriedSnowflakes();
piledFlake.display();
}
}
// snowflake class
function snowflake() {
// initialize coordinates
this.posX = 0;
this.posY = random(-50, 0);
this.initialangle = random(0, 2 * PI);
this.size = random(2, 5);
// radius of snowflake spiral
// chosen so the snowflakes are uniformly spread out in area
this.radius = sqrt(random(pow(width / 2, 2)));
this.update = function(time) {
// x position follows a circle
let w = 0.6; // angular speed
let angle = w * time + this.initialangle;
this.posX = width / 2 + this.radius * sin(angle);
// different size snowflakes fall at slightly different y speeds
this.posY += pow(this.size, 0.5);
// delete snowflake if past end of piled snow line
if (this.posY > height - piledHeight) {
// add piledSnowflake instead of deleting snowflake
piledSnowflakes.push(this);
let index = snowflakes.indexOf(this);
snowflakes.splice(index, 1);
}
};
this.display = function() {
ellipse(this.posX, this.posY, this.size);
};
// delete piledSnowflakes under piled snow line
this.deleteBuriedSnowflakes = function() {
if (this.posY > height - piledHeight + 5) {
let index = piledSnowflakes.indexOf(this);
piledSnowflakes.splice(index, 1);
}
};
}
感想
p5.jsはプログラミングの経験が多少あれば見よう見まねでいじることができ、p5.js Web Editor を使えば環境構築も不要というハードルの低さがよかったです。
しかし、使いこなして面白いものを作れるようになるには、何をどう表現するかを考える力と適切にコーディングする力の両方が必要そうで、難しさも感じました。