Let me show you how I usually do my creative coding.

An example image of an animation of rotating discs.

Let me show you how I make my work.

Let me show you how I usually do creative coding.
I usually start with some ideas (mathematical, algorithmic, etc). I never decide what I make at the start.

I started with the idea 'Equal distance angles and radii' this time.

Freely play with the idea.

At first, I play with the idea as I like.

Put circles on the location that calculated with the Perlin noise or just randomly.


Wide interval or narrow interval.


Connecting circles with lines. etc.
Then, I thought it may be interesting if I moved connected circles with the Perlin noise.

Grasp the feeling of interest.

When I feel it may be interesting, I stop free playing and pursue that interest.
I mean play hard toward the interest that I find.

I tried to make an animation of connected circles with the Perlin noise. I changed radius with the Perlin noise like this.



/**
 * How I usually do creative coding.
 * An animation of connected circles with the Perlin noise.
 * 
 * @author @deconbatch
 * @version 0.1
 * @license GPL Version 3 http://www.gnu.org/licenses/
 * Processing 3.5.3
 * 2020.10.13
 */

void setup() {
  size(640, 640);
  colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
  frameRate(24);
}

void draw() {

  int thetaMax = 12;
  int radiusMax = 20;
  ArrayList<PVector> arcs = new ArrayList<PVector>();

  // animation cycle
  float frmRatio = map(frameCount % 120, 0, 120, 0.0, TWO_PI);

  // calculate the locations with the cyclic Perlin noise
  for (int thetaCnt = 0; thetaCnt < thetaMax; thetaCnt++) {
    float noiseVal = noise(thetaCnt, 10.0 + 0.5 * cos(frmRatio), 10.0 + 0.5 * sin(frmRatio));
    arcs.add(new PVector
             (ceil(noiseVal * radiusMax) * min(width, height) * 0.5 / radiusMax,
              thetaCnt * TWO_PI / thetaMax
              ));
  }

  background(0.0, 0.0, 90.0, 100.0);
  translate(width * 0.5, height * 0.5);
  stroke(0.0, 0.0, 30.0, 100.0);

  // draw lines
  noFill();
  beginShape();
  for (PVector a : arcs) {
    vertex(a.x * cos(a.y), a.x * sin(a.y));
  }
  endShape(CLOSE);

  // draw circles
  fill(0.0, 0.0, 90.0, 100.0);
  for (PVector a : arcs) {
    ellipse(a.x * cos(a.y), a.x * sin(a.y), 20.0, 20.0);
  }
  
}


 

Amusing!
I tried to use curveVertex() to connect points smoothly and omitted drawing circles.

Amoeba!

Ummm... not bad. But I felt it come to a dead end. So I tried to change the drawing style with the same algorithm.
When I used arc().


  for (PVector a : arcs) {
    cnt++;
    arc(0.0, 0.0,
        a.x, a.x,
        a.y, a.y + TWO_PI / thetaMax,
        PIE
        );
  }

Not bad! Not bad! I felt the interest be able to go further now.

I found that the arc() with noFill() and thick strokeWeight() makes a piece of Baumkuchen.


  noFill();
  strokeWeight(30);
  strokeCap(SQUARE);
  for (PVector a : arcs) {
    cnt++;
    arc(0.0, 0.0,
        a.x, a.x,
        a.y, a.y + TWO_PI / thetaMax
        );
  }

So I combined the color pieces and made an animation of three primary color mixing.

Interesting! I can play more!

And I made three different shapes and tried to rotate these.

And then now, I can see what I want to make.

Decide what I make at last.

After playing with my interest, I wanted to make an animation of rotating color discs.
I thought it must be nice if the rotation had various rotate angles and each discs rotation timings were the same. And mixing the color of each disc would be beautiful.

 I made trial product to verify the idea.

And made a goal!

That's all.

  1. I just start with an idea how to calculate. I never start with what I want to make.
  2. I play with the idea as I like and try to find a special interest.
  3. When I find a special interest, I pursue that interest.
  4. Then, I realize what I want to make.
  5. Make it.

I've been able to make a goal this time. But not always.
If I can not find a special interest, it will come to a dead end and I do not make anything. But I'll satisfy that I played with creative coding much and had fun! 🙂

An example source code of Processing.


/**
 * You Can't Catch Me.
 * An animation of rotating discs.
 * 
 * @author @deconbatch
 * @version 0.1
 * @license GPL Version 3 http://www.gnu.org/licenses/
 * Processing 3.5.3
 * 2020.10.11
 */

int   objMax  = 4;             // object number
int   frmRate = 24;            // animation fps
int   turnMax = 5;             // turn number
float speed   = 0.5;           // rotation speed : must be > 0.0
float baseHue = random(360.0); // object color
ArrayList<Disc> objs = new ArrayList<Disc>();

void setup() {
  size(720, 720);
  colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
  rectMode(CENTER);
  frameRate(frmRate);

  // initialize object array
  for (int objCnt = 0; objCnt < objMax; objCnt++) {
    objs.add(new Disc());
  }
}

void draw() {

  if (frameCount > frmRate * turnMax / speed) {
    exit();
  }
  
  background(0.0, 0.0, 90.0, 100.0);
  translate(width * 0.5, height * 0.5);

  noFill();
  for (int objCnt = 0; objCnt < objMax; objCnt++) {
    // reset object rotate information
    if (!objs.get(objCnt).isRotating()) {
      if (frameCount >= frmRate * (turnMax - 1) / speed) {
        objs.get(objCnt).rewind(frmRate, speed);
      } else {
        if (random(1.0) < 0.5) {
          objs.get(objCnt).setRotation(frmRate, speed);
        }
      }
    }

    // draw object
    blendMode(SUBTRACT);
    stroke((baseHue + objCnt * 20.0) % 360.0, 90.0, 60.0, 100.0);
    pushMatrix();
    objs.get(objCnt).rotates();
    objs.get(objCnt).draws();
    popMatrix();

  }

  blendMode(BLEND);
  casing();
  saveFrame("frames/" + String.format("%04d", frameCount) + ".png");
  
}

/**
 * casing : draw fancy casing
 */
public void casing() {
  fill(0.0, 0.0, 0.0, 0.0);
  strokeWeight(30.0);
  stroke(0.0, 0.0, 30.0, 100.0);
  rect(0.0, 0.0, width, height);
  strokeWeight(28.0);
  stroke(0.0, 0.0, 100.0, 100.0);
  rect(0.0, 0.0, width, height);
}

/**
 * Disc
 * holds disc information and control rotation and drawing
 *
 */
class Disc {

  int arcDiv    = 8;
  int radiusDiv = 5;

  ArrayList<PVector> arcs;
  int rotateUnit;
  int rotateFrmStart;
  int rotateFrmEnd;
  float baseRotation;

  Disc() {
    baseRotation = 0.0;

    // failsafe
    rotateUnit     = 0;
    rotateFrmStart = 0;
    rotateFrmEnd   = 0;

    arcs = new ArrayList<PVector>();
    for (int arcCnt = 0; arcCnt < arcDiv; arcCnt++) {
      arcs.add(new PVector
               (
                floor(random(radiusDiv * 0.3, radiusDiv)) * min(width, height) * 0.5 / radiusDiv,
                arcCnt * TWO_PI / arcDiv
                ));
    }
  }

  /**
   * rewind : 
   * @param  _frmRate : frame rate(fps)
   * @param  _speed   : disc rotate speed
   */
  public void rewind(int _frmRate, float _speed) {
    float signBaseRot = baseRotation / abs(baseRotation);
    float rewindTheta = (abs(baseRotation) > PI) ? signBaseRot * (abs(baseRotation) - TWO_PI) : baseRotation;
    rotateUnit     = -round(rewindTheta * arcDiv / TWO_PI);
    rotateFrmStart = frameCount;
    rotateFrmEnd   = floor(rotateFrmStart + _frmRate / ((_speed <= 0.0) ? 1.0 : _speed));
  }

  /**
   * setRotation : 
   * @param  _frmRate : frame rate(fps)
   * @param  _speed   : disc rotate speed
   */
  public void setRotation(int _frmRate, float _speed) {
    rotateUnit     = round(random(-arcDiv, arcDiv) * 0.5);
    rotateFrmStart = frameCount;
    rotateFrmEnd   = floor(rotateFrmStart + _frmRate / ((_speed <= 0.0) ? 1.0 : _speed));
  }
  
  /**
   * rotates : rotate disc
   */
  public void rotates() {
    if (isRotating()) {
      if (frameCount == rotateFrmEnd) {
        baseRotation += rotateUnit * TWO_PI / arcDiv;
        baseRotation %= TWO_PI;
      } else {
        float frmRatio = map(frameCount, rotateFrmStart, rotateFrmEnd, 0.0, 1.0);
        float easeRatio = InOutCubic(frmRatio);
        rotate(rotateUnit * easeRatio * TWO_PI / arcDiv);
      }
    }
    rotate(baseRotation);
  }
  
  /**
   * draws : draw disc with arc()
   */
  public void draws() {
    noFill();
    strokeCap(SQUARE);
    for (int i = 0; i < arcs.size(); i++) {
      PVector a = arcs.get(i);
      PVector b = arcs.get((i + 1) % arcs.size());

      float w = constrain(abs(a.x - b.x), 0.0, a.x);
      float r = a.x + w * 0.5;
    
      if (w != 0.0) {
        strokeWeight(w);
        arc(
            0.0, 0.0,
            r, r,
            a.y, (a.y < b.y) ? b.y : b.y + TWO_PI
            );
      }
    }
  }

  /**
   * isRotating
   * @return : rotating = true, not rotating = false
   */
  public Boolean isRotating() {
    return (frameCount > rotateFrmEnd) ? false : true;
  }

  /**
   * easeInOutCubic easing function.
   * @param  _t    : 0.0 - 1.0 : linear value.
   * @return float : 0.0 - 1.0 : eased value.
   */
  private float InOutCubic(float _t) {
    _t *= 2.0;
    if (_t < 1.0) {
      return pow(_t, 3) / 2.0;
    }
    _t -= 2.0;
    return (pow(_t, 3) + 2.0) / 2.0;
  }
}


/*
Copyright (C) 2020- deconbatch

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>
*/


No comments :

Post a Comment