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)数学を思い出せてきてる
三角関数やベクトルの概念を少しずつ思い出せてきてる!
深まるのが楽しい
できないことができるようになる。
わからなかったことがわかる。
僕はここに楽しさを感じてしまうんだよね。
いずれ素敵な作品を魅せるためにコツコツと筋トレしているよ。