An example image of an animation of rotating discs.


Can I show you how I make my creative coding work?

Let me show you how I usually do the 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.

I'll write the 'Processing' example code in this article.

 

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 with it 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 the 'Processing'.







Please feel free to use this example code under the terms of the GPL. To see other works based on my code is my pleasure. And my honor.


/**
 * 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/>
*/