How can I make eternal cyclic animation on Twitter?
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/> */