sketch_200217f

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);
  }
}