sketch_200217f.pde
AbstractShape[] shapeList;
void setup() {
size(800, 800);
background(0);
rectMode(CENTER);
shapeList = new AbstractShape[] {
new RectShape(),
new HeartShape(),
new DiceShape(),
new CircleShape(),
new StripeShape(),
new PolkaDotShape(),
new DarkPolkaDotShape()
};
noLoop();
}
void draw() {
drawPattern();
}
void drawPattern() {
float sf = random(1.5, 2.0);
float[] denominators = new float[] {0.5, 6.0, 4.0, 3.0};
float rot = PI / denominators[(int)random(denominators.length)];
rot = rot * (random(1) > 0.5 ? -1.0 : 1.0);
translate(width / 2.0, height / 2.0);
scale(sf, sf);
rotate(rot);
background(0);
recur(new PVector(0.0, 0.0), width, 0);
}
void recur(PVector p, float s, int d) {
if (d > 1 && random(1) < float(d) / 6) {
AbstractShape shape = shapeList[(int)random(shapeList.length)];
shape.drawShape(p, s, d);
} else {
recur(new PVector(p.x + s / 4.0, p.y + s / 4.0), s / 2.0, d + 1);
recur(new PVector(p.x - s / 4.0, p.y + s / 4.0), s / 2.0, d + 1);
recur(new PVector(p.x + s / 4.0, p.y - s / 4.0), s / 2.0, d + 1);
recur(new PVector(p.x - s / 4.0, p.y - s / 4.0), s / 2.0, d + 1);
}
}
static final String timestamp(final String name, final String ext) {
return name + "-" + year() + nf(month(), 2) + nf(day(), 2) +
"-" + nf(hour(), 2) + nf(minute(), 2) + nf(second(), 2) + ext;
}
void mouseReleased() {
redraw();
}
void keyReleased() {
saveFrame(String.format("frames/%s", timestamp("Project", ".png")));
}
abstract class AbstractShape {
abstract void drawShape(PVector p, float s, int d);
}
class RectShape extends AbstractShape{
void drawShape(PVector p, float s, int d) {
fill(0);
stroke(255);
int n = (int)random(1, 5);
pushMatrix();
translate(p.x, p.y);
for (int k = 0; k < n; k++) {
rect(0, 0, s, s);
scale(1.0 / sqrt(2), 1.0 / sqrt(2)); // 回転によって外にはみ出ないようにする
rotate(PI / 4);
strokeWeight(pow(sqrt(2), k)); // scaleによって線が細くなり過ぎないようにする
}
popMatrix();
strokeWeight(1.0);
}
}
class HeartShape extends AbstractShape {
void drawShape(PVector p, float s, int d) {
fill(0);
noStroke();
color heartColor = color(255);
if (random(1) < 0.05) {
heartColor = color(240, 0, 0);
}
rect(p.x, p.y, s, s);
PShape heart = createHeart();
heart.beginShape();
heart.noStroke();
heart.fill(heartColor);
heart.endShape();
pushMatrix();
translate(p.x, p.y);
scale(s / heart.width / 2.0 * 0.98, s / heart.height / 2.0 * 0.98);
shape(heart, 0, 0);
popMatrix();
}
}
PShape createHeart() {
int N = 100;
PShape s = createShape();
s.beginShape();
for (int k = 0; k < N; k++) {
float t = TWO_PI * k / (float)N;
float x = 16 * pow(sin(t), 3);
float y = -(13 * cos(t) - 5*cos(2*t) - 2*cos(3*t) - cos(4*t));
s.vertex(x, y);
}
s.endShape(CLOSE);
return s;
}
class DiceShape extends AbstractShape {
void drawShape(PVector p, float s, int d) {
int N = 100;
float r = s / 8.0;
int number = (int)random(1, 7);
color[] dicePalette = null;
if (random(1) < 0.05) {
dicePalette = new color[] {color(255), color(0), color(240, 0, 0)};
} else {
dicePalette = new color[] {color(255), color(0), color(0)};
}
pushMatrix();
translate(p.x, p.y);
fill(0);
noStroke();
rect(0, 0, s, s);
noStroke();
fill(dicePalette[0]);
beginShape();
for (int k = 0; k < N; k++) {
float t = TWO_PI * k / (float)N;
float x = r * cos(t);
float y = r * sin(t);
if (t < PI / 2.0) {
x = x + (s / 2.0 - r);
y = y + (s / 2.0 - r);
} else if (t < PI) {
x = x - (s / 2.0 - r);
y = y + (s / 2.0 - r);
} else if (t < PI * 3 / 2) {
x = x - (s / 2.0 - r);
y = y - (s / 2.0 - r);
} else {
x = x + (s / 2.0 - r);
y = y - (s / 2.0 - r);
}
vertex(x, y);
}
endShape(CLOSE);
if (number == 1) {
fill(dicePalette[2]);
circle(0, 0, s / 4.0);
} else if (number == 2) {
fill(dicePalette[1]);
circle(s / 3.0, s / 3.0, s / 5.0);
circle(-s / 3.0, -s / 3.0, s / 5.0);
} else if (number == 3) {
fill(dicePalette[1]);
circle(s / 3.0, s / 3.0, s / 5.0);
circle(0.0, 0.0, s / 5.0);
circle(-s / 3.0, -s / 3.0, s / 5.0);
} else if (number == 4) {
fill(dicePalette[1]);
circle(s / 3.0, s / 3.0, s / 5.0);
circle(-s / 3.0, s / 3.0, s / 5.0);
circle(s / 3.0, -s / 3.0, s / 5.0);
circle(-s / 3.0, -s / 3.0, s / 5.0);
} else if (number == 5) {
fill(dicePalette[1]);
circle(0.0, 0.0, s / 5.0);
circle(s / 3.0, s / 3.0, s / 5.0);
circle(-s / 3.0, s / 3.0, s / 5.0);
circle(s / 3.0, -s / 3.0, s / 5.0);
circle(-s / 3.0, -s / 3.0, s / 5.0);
} else if (number == 6) {
fill(dicePalette[1]);
circle(s / 3.0, 0.0, s / 5.0);
circle(-s / 3.0, 0.0, s / 5.0);
circle(s / 3.0, s / 3.0, s / 5.0);
circle(-s / 3.0, s / 3.0, s / 5.0);
circle(s / 3.0, -s / 3.0, s / 5.0);
circle(-s / 3.0, -s / 3.0, s / 5.0);
}
popMatrix();
}
}
class CircleShape extends AbstractShape{
void drawShape(PVector p, float s, int d) {
fill(0);
stroke(255);
int n = (int)random(1, 6);
for (int k = 0; k < n; k++) {
circle(p.x, p.y, s - s / (float)n * k);
}
}
}
class StripeShape extends AbstractShape{
void drawShape(PVector p, float s, int d) {
boolean rotation = random(1) > 0.5;
fill(255);
noStroke();
rect(p.x, p.y, s, s);
blendMode(SUBTRACT);
int n = (int)random(1, 6) * 2;
for (int k = 0; k < n; k++) {
if (k % 2 != 0) {
if (!rotation) {
rect(p.x - s / 2.0 + s / (float)n * k, p.y, s / (float)n, s);
} else {
rect(p.x, p.y - s / 2.0 + s / (float)n * k, s, s / (float)n);
}
}
}
blendMode(BLEND);
}
}
class PolkaDotShape extends AbstractShape {
void drawShape(PVector p, float s, int d) {
fill(255);
noStroke();
rect(p.x, p.y, s, s);
blendMode(SUBTRACT);
int n = (int)random(1, 6) * 2 + 1;
float r = s / (float)n;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if ((i * n + j) % 2 == 0) {
float x = p.x - s / 2.0 + r / 2.0 + r * j;
float y = p.y - s / 2.0 + r / 2.0 + r * i;
circle(x, y, r / 2.0);
}
}
}
blendMode(BLEND);
}
}
class DarkPolkaDotShape extends AbstractShape {
void drawShape(PVector p, float s, int d) {
fill(0);
noStroke();
rect(p.x, p.y, s, s);
blendMode(ADD);
fill(255);
int n = (int)random(1, 6) * 2 + 1;
float r = s / (float)n;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if ((i * n + j) % 2 == 0) {
float x = p.x - s / 2.0 + r / 2.0 + r * j;
float y = p.y - s / 2.0 + r / 2.0 + r * i;
circle(x, y, r / 2.0);
}
}
}
blendMode(BLEND);
}
}