ユニークビジョン株式会社 Advent Calendar 2024 16日目の記事です!
年に一度のお祭り、なにか楽しいことしたい!
というわけで、コンピュータでお絵描きをします!
p5.js という JavaScript ライブラリを使います。
できました!
クリスマスっぽい!!かも、、
ソースコード
import p5 from "p5";
const sketch = (p: p5) => {
let size: number;
let cellSize: number;
let distMax: number;
let diamMax: number;
const GRID_SIZE = 50;
const FRAME_RATE = 24;
const RED = p.color(236, 31, 40, 80);
const GREEN = p.color(58, 141, 49, 80);
p.setup = () => {
size = Math.min(p.windowWidth, p.windowHeight);
cellSize = size / GRID_SIZE;
distMax = p.dist(0, 0, size / 2, size / 2);
diamMax = cellSize * 3;
p.createCanvas(size, size);
p.frameRate(FRAME_RATE);
p.noStroke();
};
p.draw = () => {
p.blendMode(p.BLEND);
p.background(0, 80);
p.blendMode(p.SCREEN);
for (let row = 0; row < GRID_SIZE; ++row) {
const centerY = (row + 0.5) * cellSize;
for (let col = 0; col < GRID_SIZE; ++col) {
const centerX = (col + 0.5) * cellSize;
const dist = p.dist(centerX, centerY, size / 2, size / 2);
const diameter = p.map(dist, 0, distMax, 0, diamMax);
p.fill(chooseColor(centerX, centerY));
p.circle(centerX, centerY, diameter);
}
}
};
function chooseColor(x: number, y: number) {
const d = p.dist(x, y, size / 2, size / 2);
const t = p.frameCount * 0.1;
const n = p.noise(d * 0.01 + p.noise(x * 0.01, y * 0.01) - t);
if (n < 0.35) {
return RED;
}
if (n > 0.65) {
return GREEN;
}
return p.color(0);
}
};
new p5(sketch);
(使い捨てのコード感が若干出ちゃってますが、ちょっとしたお絵描き用のコーディングスタイルってのがあっていいはずです!)
円の色を決めるところ(chooseColor()
)で、noise 関数というのを使っています。
Perlin ノイズ
p5.js の noise 関数は、Perlin ノイズを生成する関数です。通常の乱数生成と異なり、入力に対して「連続で滑らかな」関数です。noise 関数を使うことで、より自然なランダムを作品に取り入れることができます。
応用範囲は広く、Minecraft のような地形生成に使えることでも有名ですね。
function chooseColor(x: number, y: number) {
const d = p.dist(x, y, size / 2, size / 2);
const t = p.frameCount * 0.1;
const n = p.noise(d * 0.01 + p.noise(x * 0.01, y * 0.01) - t);
if (n < 0.35) {
return RED;
}
if (n > 0.65) {
return GREEN;
}
return p.color(0);
}
今回は、canvas の中心からの距離d
と、経過フレーム数t
に適当な係数をかけて足したものを noise 関数の入力としてます。noise 関数は 0~1 の値を取り、値の範囲で赤色と緑色を出し分けているわけです。
ただ、それだけだと対称性を持ちすぎてやや退屈だったので、x 座標と y 座標を入力とした noise である p.noise(x * 0.01, y * 0.01)
を、noise 関数の入力に噛ませてみました。
こんなふうに、noise 関数を取り入れたり、使い方にひと工夫を入れるだけで印象がガラッと変わったものになって面白いです。OpenProcessing でソースコードを編集できるので、係数の値をいじったり、sin 関数を噛ませてみたり... などぜひいろいろ遊んでみてください!
p5.js でおえかきしてみたい人へ
- p5.js Web Editorというのがあり、気軽に始められます!
- ローカルにモダンで快適な環境を構築したい場合は、Bun で p5.js の開発環境を構築するという記事が参考になります
感想
素朴なアイデアを思いついて、実装して、動かして、そのフィードバックをもとにまたアイデアを考えて... のサイクルが楽しかったです!
いま見返したら途中経過のこっちのほうが好きかもしれない...
https://openprocessing.org/sketch/2495735