p5.jsが楽しい。
参考にするのは「The Coding Train」というYouTubeチャンネル。Processingやp5.jsの中の人だと思う方が楽しそうにコーディングしてるのね。
現在は130本以上の動画があがっていて、「ふと」目にとまった動画を模写(or 移植)するようにしてる。最初は真似ることが大切だから。
先人の知識や経験に感謝。
今回「ふと」響いた動画は以下の2本。Processing(Java)からの移植だったのでJavaScriptの基礎を学ぶいい機会になりました。
- Coding Challenge #11: 3D Terrain Generation with Perlin Noise in Processing
- Coding Challenge #134: Heart Curve
3D Terrain Generation
ソースコード
const scl = 30;
const w = 1800;
const h = 1500;
let cols, rows;
let terrain = [];
let flying = 0;
let cam;
let delta = 0.01;
function setup() {
createCanvas(innerWidth, innerHeight, WEBGL);
cols = w / scl;
rows = h / scl;
frameRate(20);
// 地形データ用配列の初期化
terrain = new Array(cols);
for (let i = 0; i < cols; i++) {
terrain[i] = new Array(rows).fill(0);
}
// カメラの設定(傾きあり)
cam = createCamera();
cam.tilt(-0.7);
}
function draw() {
// 地形データ用配列に位置情報をセット
flying -= 0.5;
let yoff = flying;
for (let y = 0; y < rows; y++) {
let xoff = 0;
for (let x = 0; x < cols; x++) {
terrain[x][y] = map(noise(xoff, yoff), 0, 1, -100, 100);
xoff += 0.2;
}
yoff += 0.2;
}
// 地形を描画
background(0);
stroke(255);
noFill();
rotateX(PI/3);
translate(-w/2, -h/2);
for (let y = 0; y < rows-1; y++) {
beginShape(TRIANGLE_STRIP);
for (let x = 0; x < cols; x++) {
vertex(x*scl, y*scl, terrain[x][y]);
vertex(x*scl, (y+1)*scl, terrain[x][y+1]);
}
endShape();
}
// カメラの傾きを調整
cam.tilt(delta);
if (frameCount % 90 === 0) {
delta *= -1;
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>p5.js demo | Takashi Q. Hanamura Photograpy</title>
<style>
body {
margin: 0;
height: 0;
overflow: hidden;
}
canvas {
width: 100vw;
height: 100vh;
background: black;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/p5.min.js"></script>
<script src="sketch.js"></script>
</head>
<body>
</body>
</html>
動作画面
わかったこと
(1)作り方がわかってきた
動作させたいことを最小単位に分割すればわかりやすいし、作りやすいよね。
つまり、複雑な動きをさせるときも、一つ一つ分解して単純化すればわかりやすい。単純化したものを組み上げていくことで複雑な動き(描画)にすることができるはず。
作り方(考え方)がわかってきた。
会社員のときにシステム開発をしていたことと同じだね。おかげで基本的なことを思い出せた。昔のカンも戻ってきてると思う。
(2)ブラウザによる動作速度の違い
動作確認はSafari / Chrome / Firefoxでやりましたが、Safariが一番低負荷で高速に描画されるのが面白かった。
Chrome / FirefoxではMBPのファンが唸ってしまいます。
Heart Curve
ソースコード
let heartVector = [];
let angle = 0;
function setup() {
createCanvas(innerWidth, innerHeight);
}
function draw() {
background(0);
translate(width/2, height/2);
let r = 10;
let x = r * 16 * pow(sin(angle), 3);
let y = -r * (13 * cos(angle) - 5 * cos(2*angle) - 2 * cos(3*angle) - cos(4*angle));
heartVector.push(createVector(x, y));
angle += 0.05;
noFill();
stroke(255);
strokeWeight(4);
fill(150, 0, 100);
beginShape();
for (i of heartVector) {
vertex(i.x, i.y);
}
endShape();
if (angle >= TWO_PI) {
noLoop();
console.log("Finish");
}
}
※sketch.htmlは3D Terrain Generationと同様
動作画面
ハートが描かれます。見れない場合はリロードしてくださいね。
わかったこと
(1)JSの基礎不足
3D Terrain Generationでも感じたけど、僕はJSの配列やデータ型について理解が不足しているね。
ループ処理もなんか複雑。
JavaScriptは年々進化していると聞きます。ループ処理も昔からの「for」のほか「[…Array]」 という書き方もあって、使い分けがわかりにくい。
そんなこんなで以下の記事を参考にしながら、Heart Curveでは「for 〜 of 〜」を使うことで想定した動作をさせることができた。
思わず「よっしゃ!」って叫んじゃったよ(笑)
今のところ、JSの基礎を知るには公式(?)の情報から入っていったほうがいいのかも、と理解しました。
(2)数学を思い出せてきてる
三角関数やベクトルの概念を少しずつ思い出せてきてる!
深まるのが楽しい
できないことができるようになる。
わからなかったことがわかる。
僕はここに楽しさを感じてしまうんだよね。
いずれ素敵な作品を魅せるためにコツコツと筋トレしているよ。

