How can I make eternal cyclic animation on Twitter?

An example image of this animation.


Aiming eternal cyclic animation on Twitter on this code.

It's a creative coding animation work made with the 'Processing'.

I calculated the points with vector field calculation and I connected the points with the 'curveVertex()' function. And I animate it with the 'curveTightness()' function.

Vector field calculation.

Drawing vector field | GenerateMe 

I aimed to make eternal cyclic animation on Twitter. This Processing code generates 24fps x 6s animation frames. And start frame and end frame are connected seamlessly.

This code do not display any images on the screen but just generates image files.
You can make animation with these files.







 

The 'Processing' code example.

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

/**
 * Broken Tea Cup.
 * make vector field with Perlin noise -> node array -> draw lines with curveVertex.
 * 
 * Processing 3.2.1
 * @author @deconbatch
 * @version 0.1
 * created 0.1 2019.04.20
 */

void setup() {

  size(720, 720);
  colorMode(HSB, 360, 100, 100, 100);
  rectMode(CENTER);
  smooth();
  noLoop();

}

void draw() {
 
  int   frameCntMax = 24 * 6; // for 24fps x 6s animation
  int   shapeCntMax = 6;      // shape number must be even
  int   lineCntMax  = 8;      // lines per shape
  float plotDiv     = 0.02;   // bigger : gap of each line wider

  int   cornerCntMax = floor(random(3.0, 6.0));
  float baseHue      = random(360.0);

  NodeList[] nodeList = new NodeList[lineCntMax];
  for (int lineCnt = 0; lineCnt < lineCntMax; ++lineCnt) {
    nodeList[lineCnt] = new NodeList();
  }

  translate(width * 0.5, height * 0.5);

  for (int frameCnt = 0; frameCnt < frameCntMax; ++frameCnt) {

    float frRatio = map(frameCnt, 0, frameCntMax, 0.0, 1.0);
    background(0.0, 0.0, 90.0, 100);

    for (int shapeCnt = 0; shapeCnt < shapeCntMax; ++shapeCnt) {

      float shRatio = map(shapeCnt, 0, shapeCntMax, 0.0, 1.0);
      curveTightness(map(sin(TWO_PI * shRatio * 3.0 + PI * frRatio), -1.0, 1.0, 1.0, -1.0));

      for (int lineCnt = 0; lineCnt < lineCntMax; ++lineCnt) {
        nodeList[lineCnt].clear();
      }

      for (int cornerCnt = 0; cornerCnt < cornerCntMax; ++cornerCnt) {

        float cRatio = map(cornerCnt, 0, cornerCntMax, 0.0, 1.0);

        // size of center + location of the shape
        float xPoint = 0.03 * cos(TWO_PI * cRatio) + 0.3 * cos(TWO_PI * shRatio + PI * frRatio);
        float yPoint = 0.03 * sin(TWO_PI * cRatio) + 0.3 * sin(TWO_PI * shRatio + PI * frRatio);

        for (int lineCnt = 0; lineCnt < lineCntMax; ++lineCnt) {
          float xPrev = xPoint;
          float yPrev = yPoint;
          xPoint += plotDiv * cos(TWO_PI * (cRatio + noise(yPrev * 0.5)));
          yPoint += plotDiv * sin(TWO_PI * (cRatio + noise(xPrev * 0.5)));
          Node node = new Node(new PVector(xPoint * width, yPoint * height));
          nodeList[lineCnt].add(node);
        }

      }

      for (int lineCnt = 0; lineCnt < lineCntMax; ++lineCnt) {

        float lRatio = map(lineCnt, 0, lineCntMax, 0.0, 1.0);

        float sHue   = baseHue + lRatio * 45.0 + sin(TWO_PI * shRatio * 3.0 + PI * frRatio) * 45.0;
        float sSat   = map(sin(HALF_PI * lRatio), 0.0, 1.0, 40.0, 60.0);
        float sBri   = map(lRatio, 0.0, 1.0, 80.0, 40.0);

        noFill();
        strokeWeight(map(lRatio, 0.0, 1.0, 5.0, 1.0));
        stroke(sHue % 360.0, sSat, sBri, 50.0);
        if (lineCnt == 0) {
          float fBri   = map(sin(TWO_PI * shRatio * 3.0 + TWO_PI * frRatio), -1.0, 1.0, 90.0, 60.0);
          fill(sHue % 360.0, sSat, fBri, 100.0);
        }
        nodeList[lineCnt].connectNodes();
      }

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

  }
  exit();
}

/**
 * casing : draw fancy casing
 */
private void casing() {
  blendMode(BLEND);
  fill(0.0, 0.0, 0.0, 0.0);
  strokeWeight(55.0);
  stroke(0.0, 0.0, 0.0, 100.0);
  rect(0.0, 0.0, width, height);
  strokeWeight(50.0);
  stroke(0.0, 0.0, 100.0, 100.0);
  rect(0.0, 0.0, width, height);
  noStroke();
  noFill();
}

/**
 * Keep node information.
 * @param  _position : node position
 */
class Node {
  PVector position;
 
  Node(PVector _position) {
    position = new PVector();
    position.set(_position);
  }
}

class NodeList extends ArrayList<Node> {

  void connectNodes() {

    beginShape();
    for (int j = 0; j < 2; ++j) { // twice for nice curve
      for (int i = 0; i < this.size(); ++i) {
        Node node = this.get(i);
        curveVertex(node.position.x, node.position.y);
      }
    }
    endShape();

  }
}


/*
Copyright (C) 2019- 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/>
*/



Next Post Previous Post
No Comment
Add Comment
comment url