A creative coding animation with multiple easing functions
The magical dance of creative coding.
It's one of my creative coding animation work made with the 'Processing'.
Yet another implementation of 'I Wish I Were Your Mirror'. And I added multiple easing functions in it. Please enjoy this interesting moving.
This code does not display any images on the screen but generates image files for animation. You can make an animation with these files.
The 'Processing' code example.
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.
/** * Dance With Me. * Have a dots ball. * @author @deconbatch * @version 0.1 * Processing 3.2.1 * 2019.02.12 */ void setup() { size(720, 720); colorMode(HSB, 360, 100, 100, 100); rectMode(CENTER); smooth(); noLoop(); } void draw() { translate(width / 2.0, height / 2.0); int frameCntMax = 24 * 6; int easeLanding = 2 + floor(random(3)); // easing will stop 2, 3 or 4 times on the way float hueBase = random(360.0); float initRotation = random(PI); float initPosition = random(1.0); StepEasing se = new StepEasing(easeLanding); EasingCalculator ec = (random(1.0) > 0.5) ? new FourthPow() : new InOutCubic(); for (int frameCnt = 0; frameCnt < frameCntMax; ++frameCnt) { float easeRatio = se.calculate(ec, 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 = 6; float plotScale = width * 0.25; float plotWidth = sin(PI * _shapeFactor) * 0.08; strokeWeight(3.0); stroke(0.0, 0.0, 90.0, 100.0); for (int shapeCnt = 0; shapeCnt < 2; ++shapeCnt) { float xPrev = 0.0; float yPrev = 0.0; // rotate shape location with PI, not TWO_PI float xInit = width * plotWidth * cos(PI * (_shapeFactor + shapeCnt + _initPosition)); float yInit = height * plotWidth * sin(PI * (_shapeFactor + shapeCnt + _initPosition)); // for distorted shape float xDist = map(sin(TWO_PI * _shapeFactor), -1.0, 1.0, 0.9, 1.1); float yDist = map(xDist, 0.95, 1.05, 1.1, 0.9); float eHue = _hueBase + map(sin(TWO_PI * (_shapeFactor + shapeCnt / 3.0)), -1.0, 1.0, 0.0, 60.0); float eSize = 50.0; for (int plotCnt = 0; plotCnt < plotCntMax; ++plotCnt) { float xCurr = xInit + plotScale * cos(3.0 * TWO_PI * plotCnt * 1.0 / plotCntMax + TWO_PI * _shapeFactor); float yCurr = yInit + plotScale * sin(2.0 * TWO_PI * plotCnt * 1.0 / plotCntMax ); 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(); } /** * StepEasing : calculate easing value with step landing. It just has one easing function yet. * @param _landingCount : 1 - any int value : landing number. */ private class StepEasing { private float landingPoint; private float easePrev; private float easeRatio; StepEasing(int _landingCount) { landingPoint = 1.0 / (_landingCount + 1); reset(); } StepEasing() { 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(EasingCalculator _calc, float _t) { float easeCurr = _calc.calculate(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. */ interface EasingCalculator { float calculate(float _t); } private class InOutCubic implements EasingCalculator { public float calculate(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; } } private class Squre implements EasingCalculator { public float calculate(float _t) { return 1.0 - pow(1.0 - _t, 2); } } private class FourthPow implements EasingCalculator { public float calculate(float _t) { return 1.0 - pow(1.0 - _t, 4); } } /* 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/> */