4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ユニークビジョン株式会社Advent Calendar 2024

Day 16

p5.js でおえかきしよう!

Last updated at Posted at 2024-12-23

ユニークビジョン株式会社 Advent Calendar 2024 16日目の記事です!

年に一度のお祭り、なにか楽しいことしたい!

というわけで、コンピュータでお絵描きをします!
p5.js という JavaScript ライブラリを使います。

できました!

クリスマスっぽい!!かも、、

ソースコード

sketch.ts
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 でおえかきしてみたい人へ

感想

素朴なアイデアを思いついて、実装して、動かして、そのフィードバックをもとにまたアイデアを考えて... のサイクルが楽しかったです!

いま見返したら途中経過のこっちのほうが好きかもしれない...
https://openprocessing.org/sketch/2495735

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?