
const CONFIG = {
canvasSize: 1000,
bgColor: 15,
fillColor: [30, 190, 180],
maxAttempts: 5000,
minRadius: 5,
};
let circles = [];
let attempts = 0;
function setup() {
createCanvas(CONFIG.canvasSize, CONFIG.canvasSize);
background(CONFIG.bgColor);
noStroke();
}
function draw() {
if (attempts >= CONFIG.maxAttempts) {
noLoop();
return;
}
const pos = { x: random(width), y: random(height) };
const maxR = findMaxRadius(pos.x, pos.y);
if (maxR >= CONFIG.minRadius) {
addCircle(pos.x, pos.y, maxR);
attempts = 0;
} else {
attempts++;
}
}
function addCircle(x, y, r) {
circles.push({ x, y, r });
fill(...CONFIG.fillColor, random(100, 255));
circle(x, y, r * 2);
}
function findMaxRadius(x, y) {
let maxR = min(x, y, width - x, height - y);
for (const c of circles) {
const d = dist(x, y, c.x, c.y);
maxR = min(maxR, d - c.r);
}
return max(maxR, 0);
}
function mousePressed() {
circles = [];
attempts = 0;
background(CONFIG.bgColor);
loop();
}
// ์ ์ญ ์ค์ ๊ฐ์ฒด
const CONFIG = {
canvasSize: 1000, // ์บ๋ฒ์ค ๊ฐ๋กยท์ธ๋ก ๊ธธ์ด (์ ์ฌ๊ฐํ)
bgColor: 15, // ๋ฐฐ๊ฒฝ์ (0-255 grayScale ๊ฐ, 15 = ๋งค์ฐ ์ด๋์ด ํ์)
fillColor: [30, 190, 180], // ์ฑ์ฐ๊ธฐ ์์ (RGB ๊ธฐ๋ฐ)
maxAttempts: 5000, // ํ ํ๋ ์์ ์์ ๊ทธ๋ฆด ๋ ํ์ฉํ ์ต๋ ์ฌ์๋ ํ์
minRadius: 5, // ๊ทธ๋ ค์ง ์์ ์ต์ ๋ฐ์ง๋ฆ (์ด๋ณด๋ค ์์ผ๋ฉด ํฌ๊ธฐ)
};
// ์ด๋ฏธ ์์ฑ๋ ์(์ขํ+๋ฐ์ง๋ฆ)๋ค์ ์ ์ฅํ ๋ฐฐ์ด
let circles = [];
// ํ์ฌ ํ๋ ์์์ ์ฐ์์ผ๋ก โ์คํจโํ ํ์๋ฅผ ์
๋ณ์
let attempts = 0;
function setup() {
// p5.js๊ฐ ์ ๊ณตํ๋ createCanvas๋ก 1000ร1000 ํฝ์
์ง์ฌ๊ฐํ ์บ๋ฒ์ค ์์ฑ
createCanvas(CONFIG.canvasSize, CONFIG.canvasSize);
// ๋ฐฐ๊ฒฝ ํ ๋ฒ ์น ํ๊ธฐ (grayScale 15 = ๊ฑฐ์ ๊ฒ์์์ ๊ฐ๊น์ด ํ์)
background(CONFIG.bgColor);
// stroke(์ค๊ณฝ์ )์ ๋๋ฉด ์์ด ํ
๋๋ฆฌ ์์ด ๊น๋ํ๊ฒ ์ฑ์์ง
noStroke();
}
function draw() {
// 1. ์ต๋ ์๋ ํ์๋ฅผ ๋๊ธฐ๋ฉด ๋ ์ด์ ๊ทธ๋ฆฌ์ง ์๊ณ ๋ฃจํ ์ ์ง
if (attempts >= CONFIG.maxAttempts) {
noLoop(); // p5 ๋ฃจํ ์ค๋จ โ draw()๊ฐ ๋ ์ด์ ์๋ ํธ์ถ ์ ๋จ
return;
}
// 2. ์บ๋ฒ์ค ์์ ์์ ํ ์ ์ ํ (0 โค x < width, 0 โค y < height)
const pos = { x: random(width), y: random(height) };
// 3. ๊ทธ ์ ์์ ๊ทธ๋ฆด ์ ์๋ โ์ต๋ ๋ฐ์ง๋ฆโ ๊ณ์ฐ (ํ๋ฉด ๊ฒฝ๊ณ+๊ธฐ์กด ์๊ณผ ๊ฒน์น์ง ์๋๋ก)
const maxR = findMaxRadius(pos.x, pos.y);
// 4. ์ต์ ๋ฐ์ง๋ฆ ์ด์์ ๊ณต๊ฐ์ด ํ๋ณด๋๋ฉด ์ค์ ์ ์์ฑ, ์๋๋ฉด ์๋ ํ์ ์ฆ๊ฐ
if (maxR >= CONFIG.minRadius) {
addCircle(pos.x, pos.y, maxR); // ํ๋ฉด์ ๊ทธ๋ฆฌ๊ณ ๋ฐฐ์ด์ ์ ์ฅ
attempts = 0; // ์ฐ์ ์คํจ ํ์ ์ด๊ธฐํ (์ฑ๊ณตํ์ผ๋)
} else {
attempts++; // ์คํจ ๋์
}
}
function addCircle(x, y, r) {
// ์ ์ ์ ๋ณด๋ฅผ ๋ฐฐ์ด์ push โ ๋์ค์ ์ถฉ๋ ๊ฒ์ฌ ๋ ์ฌ์ฌ์ฉ
circles.push({ x, y, r });
// fill ์์์ ์ค์ ๊ฐ(RGB) + ์ํ๊ฐ์ 100~255 ์ฌ์ด ๋๋ค
fill(...CONFIG.fillColor, random(100, 255));
// p5 circle ํจ์: (์ค์ฌx, ์ค์ฌy, ์ง๋ฆ) โ ์ง๋ฆ = ๋ฐ์ง๋ฆร2
circle(x, y, r * 2);
}
function findMaxRadius(x, y) {
// ์ผ๋จ ํ๋ฉด ๋ค ๋ณ๊น์ง์ ์ต์ ๊ฑฐ๋ฆฌ๋ฅผ ๊ตฌํด โ๊ฒฝ๊ณ๋ฐ์ผ๋ก ์์ ธ๋๊ฐ์ง ์๋โ ์ต๋ ๋ฐ์ง๋ฆ ์ด๊ธฐ๊ฐ ์ค์
let maxR = min(x, y, width - x, height - y);
// ๊ธฐ์กด์ ์์ฑ๋ ๋ชจ๋ ์๊ณผ์ ๊ฑฐ๋ฆฌ๋ฅผ ๋น๊ตํด ์๋ก ๊ฒน์น์ง ์๋๋ก โ์ฌ์ โ ํ๋ณด
for (const c of circles) {
const d = dist(x, y, c.x, c.y); // ๋ ์ ์ค์ฌ ์ฌ์ด์ ๊ฑฐ๋ฆฌ
maxR = min(maxR, d - c.r); // โ๋ด ๋ฐ์ง๋ฆโ = (์ค์ฌ๊ฐ ๊ฑฐ๋ฆฌ - ์๋ ๋ฐ์ง๋ฆ) ์ดํ
}
// ์์๊ฐ ๋์ฌ ์ ์์ผ๋ฏ๋ก 0 ์ด์์ผ๋ก ํด๋จํ
return max(maxR, 0);
}
function mousePressed() {
// ๋ง์ฐ์ค๋ฅผ ํด๋ฆญํ๋ฉด ์ด๊ธฐํ
circles = []; // ์ ์ฅ๋ ์ ์ ๋ณด ์ ๋ถ ์ญ์
attempts = 0; // ์คํจ ํ์ ๋ฆฌ์
background(CONFIG.bgColor); // ๋ฐฐ๊ฒฝ์์ผ๋ก ๋ค์ ์น ํ๊ธฐ
loop(); // ํน์ noLoop ์ํ์๋ค๋ฉด draw ์ฌ์์
}