Dancing Lissajous-like figures in a step-easing move
Dance of Lissajous-like figures.
It's a creative coding animation work made with the 'Processing'.
My last work 'Piece in the Shape of a Square' became Lissajous like figures with some modification. I organized it in 2 shape rotate animation.
And I introduced a new easing class. This easing class provides step landing easing.
Two landing easing
An example 'Processing' code.
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.
This code does not display any images on screen but generates image files for animation. You can make an animation with these files.
// I Wish I Were Your Mirror. // @author @deconbatch // @version 0.1 // Processing 3.2.1 // 2019.02.08 void setup() { size(720, 720); colorMode(HSB, 360, 100, 100, 100); rectMode(CENTER); smooth(); noLoop(); // fix 0, 5, 10 or 15 for nice shape. // But I don't know it would work or not on other environment. noiseSeed(floor(random(4.0)) * 5); } void draw() { translate(width / 2.0, height / 2.0); noStroke(); int frameCntMax = 24 * 6; int easeLanding = 1 + floor(random(3)); // easing will stop 1, 2 or 3 times on the way float hueBase = random(360.0); float initRotation = random(PI); float initPosition = random(1.0); Easing es = new Easing(easeLanding); for (int frameCnt = 0; frameCnt < frameCntMax; ++frameCnt) { float easeRatio = es.calculate(map(frameCnt, 0, frameCntMax, 0.0, 1.0)); background(0.0, 0.0, 90.0, 100); pushMatrix(); rotate(initRotation); drawShapes(hueBase, initPosition, easeRatio); popMatrix(); casing(hueBase); saveFrame("frames/" + String.format("%04d", frameCnt) + ".png"); } exit(); } /** * drawShapes : draw 2 shapes with Lissajous like figure. * @param _hueBase : 0.0 - 360.0 : base color of shape. * @param _initPosition : 0.0 - 1.0 : start position of shape. * @param _shapeFactor : 0.0 - 1.0 : change factor of shape. */ private void drawShapes(float _hueBase, float _initPosition, float _shapeFactor) { int plotCntMax = 15000; float plotScale = 0.00024; for (int shapeCnt = 0; shapeCnt < 2; ++shapeCnt) { float xPrev = 0.0; float yPrev = 0.0; // rotate shape location with PI, not TWO_PI float xCurr = width * 0.24 * cos(PI * (_shapeFactor + shapeCnt + _initPosition)); float yCurr = height * 0.24 * sin(PI * (_shapeFactor + shapeCnt + _initPosition)); // for distorted shape float xDist = map(sin(TWO_PI * _shapeFactor), -1.0, 1.0, 0.95, 1.05); float yDist = map(xDist, 0.95, 1.05, 1.05, 0.95); float eHue = _hueBase + map(sin(TWO_PI * (_shapeFactor + shapeCnt * 0.5)), -1.0, 1.0, 0.0, 60.0); for (int plotCnt = 0; plotCnt < plotCntMax; ++plotCnt) { // As usual, I don't know why this formula make such a shape... xPrev += plotScale * cos(TWO_PI * noise(xCurr * 0.001, yCurr * 0.001) * 0.18) * xDist; yPrev += plotScale * sin(TWO_PI * noise(yCurr * 0.001, xCurr * 0.001) * 0.5) * yDist; xCurr += cos(TWO_PI * xPrev * 8.0); yCurr += cos(TWO_PI * yPrev * 8.0); float eSize = map(sin(PI * map(plotCnt, 0, plotCntMax, 0.0, 1.0)), 0.0, 1.0, 0.0, 3.0); fill( eHue % 360.0, map(plotCnt, 0, plotCntMax, 40.0, 10.0), map(plotCnt, 0, plotCntMax, 30.0, 80.0), 100.0 ); ellipse(xCurr, yCurr, eSize, eSize); } } } /** * casing : draw fancy casing * @param _hueBase : 0.0 - 360.0 : casing color. */ private void casing(float _hueBase) { fill(0.0, 0.0, 0.0, 0.0); strokeWeight(54.0); stroke(_hueBase, 80.0, 30.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(); } /** * Easing : calculate easing value with step landing. It just has one easing function yet. * @param _landingCount : 1 - any int value : landing number. */ private class Easing { private float landingPoint; private float easePrev; private float easeRatio; Easing(int _landingCount) { landingPoint = 1.0 / (_landingCount + 1); reset(); } Easing() { landingPoint = 1.0; reset(); } private void reset() { easePrev = 0.0; easeRatio = 0.0; } /** * calculate : calculate easing value with step landing. * @param _t 0.0 - 1.0 : linear value. * @return float 0.0 - 1.0 : eased value with step landing. */ public float calculate(float _t) { float easeCurr = easeInOutCubic(map(_t % landingPoint, 0.0, landingPoint, 0.0, 1.0)); easeRatio += constrain((easeCurr - easePrev) * landingPoint, 0.0, 1.0); easePrev = easeCurr; return easeRatio; } /** * easeInOutCubic easing function. * @param _t : 0.0 - 1.0 : linear value. * @return float : 0.0 - 1.0 : eased value. */ private float easeInOutCubic(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) 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/> */
Yet another example image.
<